delete() from the script and the interpretator gives a different result. Why? - tarantool

Function from script:
function test_delete(val)
local result = box.space.upbx_test_redirections.index.name_index:delete(val)
return result
end
I get: "message":"Get() doesn't support partial keys and non-unique indexes".
If I call from the interpreter, everything is OK, i get tuple. Options my index
name_index: 3: &3
unique: true
parts:
- type: string
is_nullable: false
fieldno: 4
id: 3
type: TREE
space_id: 517
name: name_index
bucket_id: *1
index_name: *3
ID: *0
secondary: *2
value for test:1234567890abcdefghijkl0987654321_uuid
Code for create space:
local upbx_test_redirections = box.schema.space.create(
"upbx_test_redirections",
{
format = {
{"ID", "integer"},
{"bucket_id", "unsigned"},
{"test1", "string"},
{"test2", "string"},
{"test3", "string"},
{"test4", "string"},
{"test5", "string"},
{"test6", "string"},
{"test7", "string"},
{"test8", "string"},
{"test9", "integer"},
{"test10", "integer"},
},
if_not_exists = true,
}
)
and index:
upbx_test_redirections:create_index(
"name_index",
{
parts = {"test2"},
unique = true,
if_not_exists = true,
}
)
Solution: need changed in all instances.

I'd recommend you revise your schema again.
My hypothesis - previously you created non-unique index and then just modify unique=false to unique=true.
tarantool> upbx_test_redirections:create_index(
> "name_index",
> {
> parts = {"test2"},
> unique = false,
> if_not_exists = true,
> }
> )
---
- unique: false
parts:
- type: string
is_nullable: false
fieldno: 4
id: 1
space_id: 512
type: TREE
name: name_index
...
tarantool> upbx_test_redirections:create_index(
> "name_index",
> {
> parts = {"test2"},
> unique = true,
> if_not_exists = true,
> }
> )
---
- unique: false -- unique option isn't changed
parts:
- type: string
is_nullable: false
fieldno: 4
id: 1
space_id: 512
type: TREE
name: name_index
- not created
...
See my example with errors that you could face.
box.cfg{}
s = box.schema.space.create('test')
s:format({{name = 'id', type = 'unsigned'}, {name = 'value', type = 'string'}})
-- Unique primary index
s:create_index('pk', {unique = true, parts = {{field = 'id', is_nullable = false}}})
-- Unique secondary index
s:create_index('sk', {unique = true, parts = {{field = 'value', is_nullable = false}}})
-- Unique multipart index
s:create_index('multipart', {unique = true, parts = {{field = 'id', is_nullable = false}, {field = 'value', is_nullable = false}}})
-- Non-unique multipart indexes
s:create_index('multipart_non_unique', {unique = false, parts = {{field = 'id', is_nullable = false}, {field = 'value', is_nullable = false}}})
-- Test data
s:replace{1, '1'}
s:replace{2, '2'}
s:replace{3, '3'}
s:replace{4, '4'}
s:replace{5, '5'}
-- Examples with errors
box.space.test:delete({1}) -- OK
box.space.test.index['pk']:delete({2}) -- OK
box.space.test.index['pk']:delete(2) -- OK
box.space.test.index['pk']:delete(nil) -- Fail
box.space.test.index['sk']:delete('3') -- OK
box.space.test.index['sk']:delete({'3'}) -- OK
box.space.test.index['multipart']:delete({4}) -- Fail: Invalid key part count in an exact match (expected 2, got 1)
box.space.test.index['multipart']:delete({4, '4'}) -- OK
box.space.test.index['multipart_non_unique']:delete({5}) -- Fail: Get() doesn't support partial keys and non-unique indexes
box.space.test.index['multipart_non_unique']:delete({5, '5'}) -- Fail: Get() doesn't support partial keys and non-unique indexes
If problem still exists feel free to report a bug

Related

Query trougth yaml with terraform

Hello i am trying to get a specific value out of my yaml file.
gitlab_project_id: 1222
name: testing-all
hostnames:
- name: testing-a
external: true
internal: true
internal_stages: ["dev","qs"]
- name: testing-b
external: true
internal: true
internal_stages: ["dev","qs"]
I am using terraform locals to get the yaml data:
applications = [for filename in fileset(path.module, "apps/*.yml") : yamldecode(file(filename))]
In my query I am referring just to the first element inside hostnames, but if I delete the index after hostnames, the list is empty.
my_query = { for app_name, hostnames in { for app in local.applications : replace(lower(app.name), "/[\\s-]+/", "-") => app.hostnames if can(app.hostnames) } : app_name => hostnames.0 if try(hostnames.0.internal, false) }
My goal is to get a output something like this:
testing-all = {
external = true
internal = true
internal_stages = [
"dev",
"qs",
]
name = "testing-a"
},{
external = true
internal = true
internal_stages = [
"dev",
"qs",
]
name = "testing-b"
}
While it is slightly unclear what you're after, it is clear you're probably over-complicating this a fair bit. First, I'm not sure if there are multiple yaml files, and you need to group them, or if there is one and you are just trying to matching it without giving the name explicitly. So, I've assumed there could be multiple and created a second. They are as follows.
apps/testing-all.yml
gitlab_project_id: 1222
name: testing-all
hostnames:
- name: testing-a
external: true
internal: true
internal_stages: ["dev","qs"]
- name: testing-b
external: true
internal: true
internal_stages: ["dev","qs"]
apps/testing-other.yml
gitlab_project_id: 5678
name: testing-other
hostnames:
- name: testing-y
external: true
internal: true
internal_stages: ["dev","qs"]
- name: testing-z
external: true
internal: true
internal_stages: ["dev","qs"]
The next issue is that your sample data, simply isn't valid data. You can't just connect objects with a comma, so I assume what you are after is a list of objects, one each per file / application, containing a list of objects housing the data within hostnames as shown.
This is done with:
main.tf
locals {
applications = [
for filename in fileset(path.module, "apps/*.yml")
: yamldecode(file(filename))
]
}
output "application_map" {
value = {
for app in local.applications
: app.name => app.hostnames
}
}
Which yields:
Changes to Outputs:
+ application_map = {
+ testing-all = [
+ {
+ external = true
+ internal = true
+ internal_stages = [
+ "dev",
+ "qs",
]
+ name = "testing-a"
},
+ {
+ external = true
+ internal = true
+ internal_stages = [
+ "dev",
+ "qs",
]
+ name = "testing-b"
},
]
+ testing-other = [
+ {
+ external = true
+ internal = true
+ internal_stages = [
+ "dev",
+ "qs",
]
+ name = "testing-y"
},
+ {
+ external = true
+ internal = true
+ internal_stages = [
+ "dev",
+ "qs",
]
+ name = "testing-z"
},
]
}

How can I get which object changed in a BehaviourSubject in RxJs?

I am listening to an observable an after the first emit with all the objects, I would to get only the object that changed. So if I have:
[{name: 'Mark'},{name: 'Joe'}]
and then a name change I only get the object that changed. So if the object becomes:
[{name: 'Jean Mark'},{name: 'Joe'}]
I only get
[{name: 'Jean Mark'}]
Your Observable emits arrays and you want to know the difference between the currently emitted array and the previous one. Tracking array state changes has more to do with how to compare arrays or objects than with Observables.
If you want to track changes within an Observable it really comes down to comparing a previous with a current value. The logic you want to use here is up to you. e.g. you have to think about how to distinguish between a 'modified' value and newly 'added' value in an array?
Check out these questions to get you started:
How to get the difference between two arrays in JavaScript?
Comparing Arrays of Objects in JavaScript
How to determine equality for two JavaScript objects?
You can compare the current value cv to the previous one pv in an Observable by using pairwise. Here is a how it could look like.
const source = of(
[{ name: "Mark", p: 2 }, { name: "Joe", p: 3 }],
[{ name: "Jean Mark", p: 2 }, { name: "Joe", p: 3 }],
[{ name: "Jean Mark", p: 1 }, { name: "Joe", p: 3 }, { name: 'Alice' }],
[{ name: "Jean Mark", p: 1 }, { name: "Joe", p: 3 }],
[{ name: "Jean Mark", p: 1 }, { name: "Joe", p: 4 }],
[{ name: "Jean Mark", p: 1 }, { name: "Joe", p: 4 }]
);
// compare two objects
const objectsEqual = (o1, o2) =>
typeof o1 === "object" && Object.keys(o1).length > 0
? Object.keys(o1).length === Object.keys(o2).length &&
Object.keys(o1).every(p => objectsEqual(o1[p], o2[p]))
: o1 === o2;
// compare two arrays
// REPLACE this function with YOUR OWN LOGIC to get your desired output !!!
const difference = (prev, curr) => ({
added: curr.filter(o1 => !prev.some(o2 => objectsEqual(o1, o2))),
removed: prev.filter(o1 => !curr.some(o2 => objectsEqual(o1, o2)))
})
source.pipe(
startWith([]), // used so that pairwise emits the first value immediately
pairwise(), // emit previous and current value
map(([pv, cv]) => difference(pv, cv)) // map to difference between pv and cv
).subscribe(console.log);
https://stackblitz.com/edit/rxjs-m9ngjy?file=index.ts
You can watch an array (index value/add/remove) with javascript proxy, but that doesn't watch for object change in the array.
const handler = {
set: function(target, property, value, receiver){
console.log('setting ' + property + ' for ' + target + ' with value ' + value);
target[property] = value;
return true;
}
}
const arr=[{name: 'Mark'},{name: 'Joe'}];
const proxy = new Proxy(arr, handler);
// will log
proxy[0]="hello"
// won't log
proxy[0].name="ben"
if you also want to watch for object change then you need to either use proxy for every object added, or create your to be added object with Object.defineProperty()
and add your setter
There is also an existing library that watch for both object and array change, and it also use proxy
https://github.com/ElliotNB/observable-slim/

Expressing a complex structure in Terraform and reading it in Go

Note: edited after a comment from #JimB
I am trying to build a new Terraform provider in Go. The resource that I need is a bit complex. It includes structures, arrays within structures, arrays and structures within arrays. When I run Terraform, it gives me errors, for example:
panic: Error reading level config: '' expected type 'string', got unconvertible type 'map[string]interface {}'. I can't figure out what I am doing wrong.
When I make the structures simple enough, they do work, but I need this resource and I'm sure there's a way to do it, and I'm just missing something perhaps trivial.
-- Here's the Terraform structure:
resource "struct" "my-struct-1" {
name = "MyFile"
complexstruct = [{
onebool = true
onearray = [{
name = "name-1"
value = "value-1"
}, {
name = "name-2"
value = "value-2"
}]
internalstruct = [{
attr1 = false
attr2 = "attribute"
}]
}]
array = [
{
attrib1 = "attrib1.1"
attrib2 = false
attrib3 = "attrib1.3"
},
{
attrib1 = "attrib2.1"
attrib2 = true
attrib3 = "attrib2.3"
}
]
}
-- Here is the Schema definition in go, as simplified as I could make it:
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"complexstruct": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"onebool": {
Type: schema.TypeBool,
Optional: true,
},
"onearray": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
},
"value": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"internalstruct": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"attr1": {
Type: schema.TypeBool,
Optional: true,
},
"attr2": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
},
},
},
"array": {
Type: schema.TypeList,
Optional: true,
Elem: map[string]*schema.Schema{
"attrib1": {
Type: schema.TypeString,
Optional: true,
},
"attrib2": {
Type: schema.TypeBool,
Optional: true,
},
"attrib3": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
----- And lastly, here's the code that I am trying to use (however, I think the problem is before it starts with the code itself):
fname := d.Get("name").(string)
d.SetId(fname)
if _, ok := d.GetOk("complexstruct"); ok {
fc := d.Get("complexstruct").([]map[string]interface{})
myBool := fc[0]["onebool"].(bool)
myArray := fc[0]["onearray"].([]map[string]interface{})
type fcS struct {
Name string `json:"name"`
Value string `json:"value"`
}
fcs := make([]fcS, len(myArray))
for ifc := range myArray {
fcs[ifc].Name = myArray[ifc]["name"].(string)
fcs[ifc].Value = myArray[ifc]["value"].(string)
}
myInternalStruct := fc[0]["internalstruct"].([]map[string]interface{})
type misS struct {
Attr1 bool `json:"attr1"`
Attr2 string `json:"attr2"'`
}
var mis misS
mis.Attr1 = myInternalStruct[0]["attr1"].(bool)
mis.Attr2 = myInternalStruct[0]["attr2"].(string)
type myWholeStruct struct {
MyBool bool `json:"onebool"`
MyArray []fcS `json:"onearray"`
MyInter misS `json:"internalstruct"`
}
outp := myWholeStruct{
myBool,
fcs,
mis,
}
o, _ := json.Marshal(outp)
writeStringToFile(string(o), fname, false)
}
Well, I expect the create function to create a file with the name taken from the name attribute, and the data a JSON representation of the values of the other Terraform attributes. Instead I am getting errors as specified above.

jqGrid - type of modifed data are changed to string

I use jqGrid and I loads data from server via AJAX. My data are {id: number, abberaviation: string, rate: float} (Id is same like Id in database). Then I will pass data to jqGrid. User is editing data on page. Then user will click on submit and I want to send data to server, but data has wrong datatypes {id: string, abberaviation: string, rate: string}.
I am getting data via getRowData function and I don't know how to send data with the same datatypes as originally received from the server.
I must retyped all datatypes on right datatypes, which server is expecting.
UPDATED
params = null
notice = null
$(document).ready () ->
params = JSON.parse $("#params").html()
notice = $("#notice")
table = $("#table")
$.jgrid.no_legacy_api = true
lastSelectedRowId = null
table.jqGrid(
datatype: "clientSide" # load from array in js
data: params.data # data array
width: "100%"
height: "100%"
colNames: ['','Měna', 'Kurz', 'Akce']
colModel: [
{
index: 'id',
name: 'id',
width: 55,
editable: false,
sortable: false,
hidden: true,
}, {
index: 'abbreviation',
name: 'abbreviation',
width: 90,
align: "center",
editable: true,
sortable: false
}, {
index: 'rate',
name: 'rate',
width: 100,
align: "center",
editable: true,
sortable: false
}, {
name: 'action',
width: 40,
align: "center",
editable: false,
formatter:'actions',
fixed: true,
resize: false,
formatoptions: { keys: true, editbutton: false }
}
]
pager: "#status"
editurl: "clientArray" # data won't be posted to the server but rather is saved only to the grid
# sortname: 'id'
# sortorder: "desc"
rowList: [] # disable page size dropdown
pgbuttons: false # disable page control like next, back button
pgtext: null # disable pager text like 'Page 0 of 10'
viewrecords: true # show total number of records 'View X to Y out of Z'
onSelectRow: (rowId) ->
console.log "rowId #{rowId} #{lastSelectedRowId}"
if lastSelectedRowId and rowId isnt lastSelectedRowId
table.jqGrid 'saveRow', lastSelectedRowId
ondblClickRow: (rowId, iRow, iCol, e) ->
console.log "rowId #{rowId} #{lastSelectedRowId}"
if rowId and rowId isnt lastSelectedRowId
console.log e.target
table.jqGrid 'editRow', rowId, true
$("input, select", e.target).focus()
lastSelectedRowId = rowId
)
table.bind("jqGridInlineAfterSaveRow", (e, rowid, orgClickEvent) ->
console.log "jqGridInlineAfterSaveRow"
console.log "lastSelectedRowId = null"
lastSelectedRowId = null
)
table.bind("jqGridInlineAfterRestoreRow", (e, rowid, orgClickEvent) ->
console.log "jqGridInlineAfterRestoreRow"
console.log "lastSelectedRowId = null"
lastSelectedRowId = null
)
$("#add-row").click (e) ->
e.preventDefault()
# table.jqGrid "editCell", 1, 1, false
table.jqGrid "addRowData", undefined, "last"
$("#save").click (e) ->
e.preventDefault()
showNotice "Probíhá ukládání na server..."
data = table.jqGrid "getRowData"
for i in [0...data.length] by 1
item = data[i]
item.id = Number item.id
if item.id is 0
delete data[i]
else if item.id is "NaN"
item.id = null
item.order = i
item.rate = Number item.rate
jsonData = JSON.stringify data
# $.ajax
# url: params.action
# type: "POST"
# data: token: params.token, data: jsonData
# success: (res) ->
# token = res.token
# console.log res.data
# showNotice "Data byla úspěšně uložena."
# error: (error) ->
# errText = JSON.parse error.responseText
# showNotice "Response #{error.status}: #{errText.msg}"
# console.log error
showNotice = (msg) ->
notice.html msg
notice.parent().removeClass "hidden"
After a long discussion of your problem I could understand that the origin of your problem is changing of type of JavaScript data of local data parameter. You use inline editing to edit the data. So you can use aftersavefunc callback to fix the problem.
I prepared the demo which demonstrates the solution. You can validate that $grid.jqGrid("getGridParam", "data"); will returns modified data where the types of the data are not changes. The property closed of the modified data will stayboolean and the properties tax, amount and total will be stay numbers. The code of aftersavefunc used as editRow parameter is the following:
aftersavefunc: function (rowid, resp, tmp, o) {
var rowItem = $(this).jqGrid("getLocalRow", rowid);
rowItem.closed = rowItem.closed === "Yes";
rowItem.tax = parseFloat(rowItem.tax);
rowItem.amount = parseFloat(rowItem.amount);
rowItem.total = parseFloat(rowItem.total);
}

Kendo UI Grid inline edit define custom values for min validation

I am using Kendo grid and want to validate one field's min value by another field from same record.
Meaning my data is like this :-
var courses = [{
CourseID : 1,
CourseName : "iPhone",
MinAge: 12,
MaxAge : 22,
MinAgeThreshold : 10,
MaxAgeThreshold : 30,
StartDate: "12/10/2014",
},
{
CourseID : 2,
CourseName : "Android",
MinAge: 12,
MaxAge : 22,
MinAgeThreshold : 10,
MaxAgeThreshold : 30,
StartDate: "12/10/2014",
}]
and I want to use MinAgeThreshold value in MinAge's validation min value, something like this:-
schema: {
model: {
id: "CourseID",
fields: {
CourseID: { editable: false, nullable: true },
StartDate: { editable: false, nullable: true },
CourseName: { editable: false, nullable: true },
MinAgeThreshold: { editable: false, nullable: true },
MinAge: { type: "number", validation: { required: true, min: MinAgeThreshold} },
MaxAge: { type: "number", validation: { required: true, min: 1} },
}
Is this possible somehow?
I tried to use in validation custom function like this
MinAge: {
type: "number",
validation: {
required: true,
minagevalidation: function (input) {
}
},
but I was not able to retrieve the values of MinAgeThreshold in minagevalidation function.
Any help would be greatly appreciated.
Regards
you can try something like given below to give the custom validation message and force the user to set value greater than the minimum value based on other input field in the same kendo grid.
MinAge: { type: "number",
validation: {
required: true,
MinAgevalidation: function (input) {
if(input.is("[name='MinAge']") &&(parseInt($("input[type='text'][name='MinAge']").val()) < parseInt($("input[type='text'][name='UnitPrice']").val()))){
input.attr("data-MinAgevalidation-msg", "MinAge should greater than MinAge threshold");
return false;
}
return true;
}
sample jsfiddle to set minimum value of one field based on other field's value .
I think I might have a solution for that kind of a problem. If you want to set the max of a field by the value of a different field you can add that to the grid edit method of your kendogrid.
var grid = $("#grid").kendoGrid({
edit: function(e){
if ( e.container.find("input[data-find='value:MinAge']).length != 0 ){
var numericTextBox = e.container.find("input[data-find='value:MinAge']).data("kendoNumericTextBox");
numericTextBox.min(e.model.MinAgeThreshold);
}
}
});
This will set the numerictTextBox of the MinAge input to min of the MinAgeThreshold that is in the dataItem of the row (model). That works with step, max, and so on as well. Edit is triggered when you enter the field. So if the initial value is 0 and your MinAgeThreshold is something else it will then switch to the MinAgeThreshold.

Resources