How to update record value in SML? - functional-programming

I am writing SML program to update records in a list.For example, I have type person_name.
type person_name = {fname:string, lname:string, mname:string}
Then I have person_bio which has person_name embedded in it.
type person_bio = {age:real, gender:string, name:person_name, status:string}
Next I have employee which has person_bio.
type employee = {p:person_bio, payrate:real, whours:real} list;
Now, I have to define function 'updateLastName' by passing the first name.
As of now, created one record 'e1' with below data.
{p={age=40.0,gender="M",name{fname="rob",lname="sen",mname=""},status="M"},
payrate=30.0,whours=10.0}
But I am facing challenge to traverse the list and then updating one field in record.
fun updateLastName(x:string,l:employee)=
if (L=[]) then []
else if (x= #fname(#name(#p hd l)) //cheking name of 1st record in list
//not getting how to update,this kind of line did not work
#fname(#name(#p hd l) = "abc"
else updateLastName(x,tl(l)); // hope this is right
Please suggest.

You have stumbled upon something difficult: Updating a deeply nested record.
For records you have getters, so #fname (#name (#p employee)) gets the field that you're checking against to know that this is the employee whose last name you are going to update. But records don't grant you equivalent setters, so you have to make those. If you're curious, lenses (Haskell) are a general way to solve this, but I don't know of any implementation of lenses for Standard ML.
I'll go ahead and remove the list part in your employee type; you should probably want an employee list if you want multiple employees modelled, rather than to say that an employee is multiple persons.
type person_name = { fname:string, lname:string, mname:string }
type person_bio = { age:real, gender:string, name:person_name, status:string }
type employee = { p:person_bio, payrate:real, whours:real }
val name1 = { fname = "John", lname = "Doe", mname = "W." } : person_name
val bio1 = { age = 42.0, gender = "M", name = name1, status = "?" } : person_bio
val my_employee1 = { p = bio1, payrate = 1000.0, whours = 37.0 } : employee
val name2 = { fname = "Freddy", lname = "Mercury", mname = "X." } : person_name
val bio2 = { age = 45.0, gender = "M", name = name2, status = "?" } : person_bio
val my_employee2 = { p = bio2, payrate = 2000.0, whours = 37.0 } : employee
val my_employees = [ my_employee1, my_employee2 ] : employee list
As for the setters (the ones that you could automatically derive using lenses),
fun setP (p : person_bio, e : employee) =
{ p = p
, payrate = #payrate e
, whours = #whours e } : employee
fun setName (name : person_name, pb : person_bio) =
{ age = #age pb
, gender = #gender pb
, name = name
, status = #status pb } : person_bio
fun setLname (lname, pn : person_name) =
{ fname = #fname pn
, lname = lname
, mname = #mname pn } : person_name
you can compose these, e.g. like:
- setP (setName (setLname ("Johnson", #name (#p my_employee1)), #p my_employee1), my_employee1)
> val it =
{p =
{age = 42.0, gender = "M",
name = {fname = "John", lname = "Johnson", mname = "W."},
status = "?"}, payrate = 1000.0, whours = 37.0} :
{p :
{age : real, gender : string,
name : {fname : string, lname : string, mname : string},
status : string}, payrate : real, whours : real}
Or you can split that line a little apart to make it more readable:
fun updateLname (fname, lname, employees) =
let fun update employee =
if #fname (#name (#p employee)) = fname
then let val new_name = setLname (lname, #name (#p employee))
val new_bio = setName (new_name, #p employee)
val new_employee = setP (new_bio, employee)
in new_employee end
else employee
in List.map update employees
end
Trying this out:
- updateLname ("Freddy", "Johnson", my_employees);
> val it =
[{p = ... {fname = "John", lname = "Doe", mname = "W."}, ... },
{p = ... {fname = "Freddy", lname = "Johnson", mname = "X."}, ... }]
- updateLname ("John", "Johnson", my_employees);
> val it =
[{p = ... {fname = "John", lname = "Johnson", mname = "W."}, ... },
{p = ... {fname = "Freddy", lname = "Mercury", mname = "X."}, ... }]

Depending on your situation, references may be appropriate here.
For any values you may need to change, you can make them a reference, i.e.
type person_name = {fname:string, lname:string ref, mname:string}
type person_bio = {age:real, gender:string, name:person_name, status:string}
fun change_lname(new_lname: string, bio: person_bio) = (#lname (#name bio)) := new_lname
val p1 = ...
print !(#lname (#name p1)) ==> LastName1
change_lname("LastName2", p1)
print !(#lname (#name p1)) ==> LastName2
If you plan on modifying data in a record a lot, it's probably a good idea to make it a reference so that your program is not rewriting memory every time it needs to change one value (though in many situations the compiler/interpreter will be able to optimize this). It also saves you from having to rewrite setter functions if the signature of your record changes. The downside is that you'll be introducing complexity into your program by using references.
For example, in the above code, we're not actually modifying p1's last name, instead p1 and a copy (passed to the function) both point to the same string, and we modify that string in the function. At no point are we actually changing any of the data in either record, we're only changing data that the records point to. It's a subtle difference, and it doesn't really make a difference in this example, but it can lead to strange bugs that are hard to debug.

Related

"TypeError: NoneType is not subscriptable" when executing multiple queries

Member function that retrieves db.
def GetDb(self):
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(self.path)
db.row_factory = sqlite3.Row
return db
Member function that returns list from db queries
def GetOrderItemsList(self, orderid):
list = []
with app.app_context():
db = self.GetDb()
cur = db.execute('SELECT * FROM ordersList WHERE orderId = ?',[orderid])
records = cur.fetchall();
for row in records:
print(row)
invid = row['inventoryId']
OrderItem
OrderItem.orderId = row['orderId']
OrderItem.productId = row['inventoryId']
OrderItem.productName = 'none'
OrderItem.quantity = row['quantity']
OrderItem.productPrice = row['price']
nextcur = db.execute('SELECT * FROM inventory WHERE invId = ?', [invid])
#nextcur = db.execute('SELECT * FROM inventory WHERE invId = 1') #works
res = nextcur.fetchone();
OrderItem.productName = res['invName']
print(res['invName'])
list.append(OrderItem)
return list
OrderItem:
class OrderItem(object):
def __init__(self, ordId, invId, name, quantity, price):
self.orderId = ordId
self.productId = invId
self.productName = name
self.quantity = quantity
self.productPrice = price
Error message:
Traceback error
OrderItem.productName = res['invName']
TypeError: 'NoneType' object is not subscriptable
Error
nextcur = db.execute('SELECT * FROM inventory WHERE invId = ?', [invid])
Works
nextcur = db.execute('SELECT * FROM inventory WHERE invId = 1')
Been fighting this for many hours. Searching on google. Reading questions on here.
Any help would be appreciated.
The error
'NoneType' object is not subscriptable
Means that you're trying to access an object's key of an object that doesn't exist, i.e. the object is None.
Please check that here
[invid]
invid is not None, i.e. print (invid)
Also, the issue could be that here
res['invName']
res is None, please check the contents of res (with print, etc) before accessing invName, as it is None.
Fix with join, item instances and img for order product list.
Inventory and OrderItems
create table inventory(invId integer PRIMARY KEY AUTOINCREMENT NOT NULL, invName varchar(50), description varchar(100), invImg varchar(50) ,category integer ,quantity integer, price real);
create table ordersList(orderId integer, inventoryId integer, orderQuantity integer, orderPrice real);
class OrderItem(object):
def __init__(self, ordId, invId, img, name, quantity, price):
self.orderId = ordId
self.productId = invId
self.productName = name
self.productImg = img
self.quantity = quantity
self.productPrice = price
def GetOrderItemsList(orderid):
list = []
db = get_db()
cur = db.execute('SELECT orderId, inventoryId, orderQuantity, orderPrice,
inventory.invName AS invName, inventory.invImg AS invImg FROM ordersList INNERJOIN
inventory ON inventory.invId= ordersList.inventoryId WHERE orderId = ?', [orderid])
records = cur.fetchall();
for row in records:
item = OrderItem(row['orderId'], row['inventoryId'],
row['invImg'], row['invName'],
row['orderQuantity'], row['orderPrice'] )
list.append(item)
return list

Get value of optional types when retrieving value of record fields in F#

I have a type defined as follows:
type Employee = {
Id: Guid
Name: string
Phone: string
Email: Option<string>
}
and an instance of this type:
let emp = {
Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
Name = "A"
Phone = "B"
Email = Some "E"
}
I want to extract the field names and values from this record type using reflection like the following:
let getFieldValueMappingOfARecordType (data: 'T) : seq<string * obj> =
let fieldValueMapping =
data.GetType()
|> FSharpType.GetRecordFields
|> Seq.map (
fun propertyInfo ->
(propertyInfo.Name, data |> propertyInfo.GetValue)
)
fieldValueMapping
Then invoking the above function with the instance of employee type
let mapping = getFieldValueMappingOfARecordType emp
|> Seq.toList
gives us:
val mapping : (string * obj) list =
[("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
("Email", Some "E")]
So far it's working well with non-optional type. But in case of optional types, it's returning the value of the field as either Some value or None. What I would like to do is to get the value when the field has Some value or make it null when it's None.
Essentially like the follwing:
val mapping : (string * obj) list =
[("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
("Email", "E")]
Or if the employee instance is like the following:
let emp = {
Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
Name = "A"
Phone = "B"
Email = None
}
Then,
val mapping : (string * obj) list =
[("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
("Email", null)]
This is what I have so far (non-working code):
open System
open Microsoft.FSharp.Reflection
open System.Reflection
type Employee = {
Id: Guid
Name: string
Phone: string
Email: Option<string>
}
let emp = {
Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
Name = "A"
Phone = "B"
Email = Some "E"
}
let getSomeOrNull (t: Type) (o: obj) =
let opt = typedefof<option<_>>.MakeGenericType [| t |]
match (o :?> opt) with
| Some s ->
s
| None ->
null
let getValues (data: 'T) =
let values =
data.GetType()
|> FSharpType.GetRecordFields
|> Array.map (
fun propertyInfo ->
let value =
data |> propertyInfo.GetValue
let isOption =
propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() = typedefof<Option<_>>
match isOption with
| true ->
(propertyInfo.Name, (getSomeOrNull propertyInfo.PropertyType value))
| false ->
(propertyInfo.Name, value)
)
values
getValues emp
|> printfn "%A"
I think the only way to do this is with reflection:
let getSomeOrNull (t: Type) (o: obj) =
if isNull o then null
else t.GetProperty("Value").GetValue(o)
I think this should do the trick:
let getSomeOrNull (o: obj) =
match o with
| :? Option<string> as o -> a |> Option.toObj > box
| _ -> null

How to create an app where user can make his own tables on sqlite and kotlin [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Well... I don't know where to start with this... I'm doing a course where the teacher has not taught us anything about databases and now he want us to do an app with kotlin and sqlite where we make an Activity with a button "New table" where user can create a database table with a name and dynamic fields. I've been searching all day about it and I got nothing.
I thought about create a CRUD but I'm with the trouble that I don't know how to make any of this dynamically.
For now I have this SQLiteHelper that I saw it was necessary to make and I put const values to test it because I don't have any clue how to pass the values from the user view.
class AdminSQLiteOpenHelper(context: Context, name: String, factory: CursorFactory?, version: Int) : SQLiteOpenHelper(context, name, factory, version) {
companion object{
const val DATABASE_NAME = "test.db"
var TABLE_NAME = "Testing_Table"
const val COL_1 = "ID"
var COL_2 = "NAME"
var COL_3 = "SURNAME"
var COL_4 = "YEARS"
}
override fun onCreate(db: SQLiteDatabase) {
db.execSQL("create table TABLE_NAME(COL_1 primary key autoincrement, COL_2 text, COL_3 text, COL_4 int)")
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("drop table if exists TABLE_NAME")
onCreate(db)
}
}
And I have this activity
class MainActivity2Crear : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_activity2_crear)
val buttonCrear = findViewById<Button>(R.id.buttonCrear)
buttonCrear.setOnClickListener{
val register = ContentValues()
register.put(COL_1, textView.getText().toString())
TABLE_NAME = register.toString()
val admin = AdminSQLiteOpenHelper(this, TABLE_NAME, null, 1)
val bd = admin.writableDatabase
bd.insert(TABLE_NAME, null, register)
bd.close()
textView.setText("")
Toast.makeText(this, "Table created", Toast.LENGTH_SHORT).show()
val intent = Intent(this, MainActivity2::class.java)
startActivity(intent)
}
val button = findViewById<Button>(R.id.button)
button.setOnClickListener{
val intent = Intent(this, MainActivity2::class.java)
startActivity(intent)
}
}
}
I just did create button for now because I don't know what I'm doing...
I know probably this question will have downvotes but I just want some help or a tutorial or something that help me to understand how to make this exercise...
You first issue that you will encounter is that you are trying to create a table using CREATE TABLE TABLE_NAME (COL_1 PRIMARY KEY AUTOINCREMENT .....
The table that will be created (attempted) will be TABLE_NAME not Testing_Table as the variable name is embedded within the String rather than being resolved and appended to the string.
There are multiple inclusions of variables in Strings.
Another error is that you have PRIMARY KEY AUTOINCREMENT autoincrement can only be used for an alias of the rowid which must be defined using specifically INTEGER PRIMARY KEY.
You don't need AUTOINCREMENT as INTEGER PRIMARY KEY will do what you want (increment the value of the ID column so the first will be 1, then likely 2, then likely 3 ....). AUTOINCREMENT is basically a constraint/rule that says the number MUST be higher (for your testing it will be (not that it really matters)).
I'd suggest the following that is based upon your code (but without the click handling) that successfully creates the table, inserts some rows (not tables) in the table and then extracts them and writes the extracted data to the log.
First the modified AdminSQLiteOpenHelper :-
class AdminSQLiteOpenHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
companion object{
const val DATABASE_NAME = "test.db"
const val DATABASE_VERSION = 1;
var TABLE_NAME = "Testing_Table"
const val COL_1 = "ID"
var COL_2 = "NAME"
var COL_3 = "SURNAME"
var COL_4 = "YEARS"
}
val db = this.writableDatabase //<<<<<<<<<< ADDED
override fun onCreate(db: SQLiteDatabase) {
//<<<<<<<<<< NUMEROUS CHANGES >>>>>>>>>>
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME +
"("
+ COL_1 + " INTEGER PRIMARY KEY," // no need for AUTOINCREMENT you want INTEGER PRIMARY KEY not PRIMARY KEY
+ COL_2 + " TEXT,"
+ COL_3 + " TEXT,"
+ COL_4 + " INTEGER" +
")"
)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("drop table if exists " + TABLE_NAME) //<<<<<<<<<<< CHANGED
onCreate(db)
}
//<<<<<<<<<< ADDED >>>>>>>>>
fun insertRow(name: String, surname: String, years: Int): Long {
val cv = ContentValues()
cv.put(COL_2,name)
cv.put(COL_3,surname)
cv.put(COL_4,years)
return db.insert(TABLE_NAME,null,cv);
}
//<<<<<<<<<< ADDED >>>>>>>>>
fun getAllRowsFromTestingTable(): Cursor {
return db.query(TABLE_NAME,null, null,null,null,null, COL_3)
}
}
please note the changes made in comparison to yours.
Now an Activity (MainActivity) that does the work of adding and extracting data from the database:-
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Get an instance of the DB Helper with full class scope
val db = AdminSQLiteOpenHelper(this)
// Add Some data
db.insertRow("Fred","Bloggs",10)
db.insertRow("Jane","Doe",25)
// Get all the data as a Cursor
val cursor = db.getAllRowsFromTestingTable()
// traverse the cursor writing data to the log
while(cursor.moveToNext()) {
Log.d("MYDATA",
"ID = " + cursor.getLong(cursor.getColumnIndex(AdminSQLiteOpenHelper.COL_1)) +
" First Name = " + cursor.getString(cursor.getColumnIndex(AdminSQLiteOpenHelper.COL_2)) +
" Surname = " + cursor.getString(cursor.getColumnIndex(AdminSQLiteOpenHelper.COL_3)) +
" Years = " + cursor.getInt(cursor.getColumnIndex(AdminSQLiteOpenHelper.COL_4))
)
}
cursor.close() //<<<<<<<<<< should ALWAYS close cursor when done
}
}
When run it produces the following in the LOG :-
2021-04-09 17:03:01.531 D/MYDATA: ID = 1 First Name = Fred Surname = Bloggs Years = 10
2021-04-09 17:03:01.531 D/MYDATA: ID = 2 First Name = Jane Surname = Doe Years = 25
Additional
Here's a revised MainActivity that has a button and will add a row to the table when it is clicked.
The rows are all the same with the exception of the years value, it being randomly generated.
After inserting the contents of the database are written to the log.
No changes to AdminSQLiteOpenHelper
:-
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Get an instance of the DB Helper with full class scope
val db = AdminSQLiteOpenHelper(this)
val buttonCrear = this.findViewById<Button>(R.id.buttonCrear)
buttonCrear.setOnClickListener{
db.insertRow("Button","Click", Random.nextInt(10,9999))
logData(db)
}
// Add Some data
db.insertRow("Fred","Bloggs",10)
db.insertRow("Jane","Doe",25)
// Get all the data as a Cursor
logData(db)
}
// Function replaces the previous logging of the data
fun logData(db: AdminSQLiteOpenHelper) {
val cursor = db.getAllRowsFromTestingTable()
while(cursor.moveToNext()) {
Log.d("MYDATA",
"ID = " + cursor.getLong(cursor.getColumnIndex(AdminSQLiteOpenHelper.COL_1)) +
" First Name = " + cursor.getString(cursor.getColumnIndex(AdminSQLiteOpenHelper.COL_2)) +
" Surname = " + cursor.getString(cursor.getColumnIndex(AdminSQLiteOpenHelper.COL_3)) +
" Years = " + cursor.getInt(cursor.getColumnIndex(AdminSQLiteOpenHelper.COL_4))
)
}
cursor.close() //<<<<<<<<<< should ALWAYS close cursor when done
}
}
Here's an example of the Log after clicking the button a few times :-
Before any Clicks
2021-04-09 18:45:47.813 D/MYDATA: ID = 1 First Name = Fred Surname = Bloggs Years = 10
2021-04-09 18:45:47.813 D/MYDATA: ID = 2 First Name = Jane Surname = Doe Years = 25
After 1st Click
2021-04-09 18:45:58.567 D/MYDATA: ID = 1 First Name = Fred Surname = Bloggs Years = 10
2021-04-09 18:45:58.567 D/MYDATA: ID = 3 First Name = Button Surname = Click Years = 9910
2021-04-09 18:45:58.567 D/MYDATA: ID = 2 First Name = Jane Surname = Doe Years = 25
After 2nd Click
2021-04-09 18:45:59.675 D/MYDATA: ID = 1 First Name = Fred Surname = Bloggs Years = 10
2021-04-09 18:45:59.675 D/MYDATA: ID = 3 First Name = Button Surname = Click Years = 9910
2021-04-09 18:45:59.675 D/MYDATA: ID = 4 First Name = Button Surname = Click Years = 8263
2021-04-09 18:45:59.676 D/MYDATA: ID = 2 First Name = Jane Surname = Doe Years = 25
After 3rd Click
2021-04-09 18:46:00.611 D/MYDATA: ID = 1 First Name = Fred Surname = Bloggs Years = 10
2021-04-09 18:46:00.611 D/MYDATA: ID = 3 First Name = Button Surname = Click Years = 9910
2021-04-09 18:46:00.611 D/MYDATA: ID = 4 First Name = Button Surname = Click Years = 8263
2021-04-09 18:46:00.612 D/MYDATA: ID = 5 First Name = Button Surname = Click Years = 9625
2021-04-09 18:46:00.613 D/MYDATA: ID = 2 First Name = Jane Surname = Doe Years = 25

terraform nested dynamic block with nested map

I'm trying to get tf 0.12.x new dynamic feature to work with a nested map, config is below.
As you can see below (simplified for this) I'm defining all the variables and adding variable required_resource_access which contains a map.
I was hoping to use new dynamic feature to create read this map in a nested dyanmic block.
variable prefix {
description = "Prefix to applied to all top level resources"
default = "abx"
}
variable suffix {
description = "Suffix to applied to all valid top level resources, usually this is 2 letter region code such as we (westeurope), ne (northeurope)."
default = "we"
}
variable env {
description = "3 letter environment code appied to all top level resources"
default = "dev"
}
variable location {
description = "Where to create all resources in Azure"
default = "westeurope"
}
variable available_to_other_tenants {
default = false
}
variable oauth2_allow_implicit_flow {
default = true
}
variable public_client {
default = false
}
# other option is native
variable application_type {
default = "webapp/api"
}
variable required_resource_access {
type = list(object({
resource_app_id = string
resource_access = object({
id = string
type = string
})
}))
default = [{
resource_app_id = "00000003-0000-0000-c000-000000000000"
resource_access = {
id = "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
type = "Role"
}
}]
}
variable reply_urls {
default = []
}
variable group_membership_claims {
default = "All"
}
resource "azuread_application" "bootstrap" {
name = "${var.prefix}-${var.env}-spn"
homepage = "http://${var.prefix}-${var.env}-spn"
identifier_uris = ["http://${var.prefix}-${var.env}-spn"]
reply_urls = var.reply_urls
available_to_other_tenants = var.available_to_other_tenants
oauth2_allow_implicit_flow = var.oauth2_allow_implicit_flow
type = var.application_type
group_membership_claims = var.group_membership_claims
dynamic "required_resource_access" {
for_each = var.required_resource_access
content {
resource_app_id = required_resource_access.value["resource_app_id"]
dynamic "resource_access" {
for_each = required_resource_access.value["resource_access"]
content {
id = resource_access.value["id"]
type = resource_access.value["type"]
}
}
}
}
}
But for reasons beyond my knowledge it keeps giving me this error (notice it's priting it twice as well), I've tried a few other options but this is the closest I managed to get where it would at least give me a meaningful error.
------------------------------------------------------------------------
Error: Invalid index
on pe_kubernetes.tf line 24, in resource "azuread_application" "bootstrap":
24: id = resource_access.value["id"]
|----------------
| resource_access.value is "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
This value does not have any indices.
Error: Invalid index
on pe_kubernetes.tf line 24, in resource "azuread_application" "bootstrap":
24: id = resource_access.value["id"]
|----------------
| resource_access.value is "Role"
This value does not have any indices.
Error: Invalid index
on pe_kubernetes.tf line 25, in resource "azuread_application" "bootstrap":
25: type = resource_access.value["type"]
|----------------
| resource_access.value is "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
This value does not have any indices.
Error: Invalid index
on pe_kubernetes.tf line 25, in resource "azuread_application" "bootstrap":
25: type = resource_access.value["type"]
|----------------
| resource_access.value is "Role"
This value does not have any indices.
Spent the best part of 2 days on this with no luck so any help or pointers would be much appreciated!
I had some time to test my comment...
If I change the resource_access to a list it works.
See code below:
variable required_resource_access {
type = list(object({
resource_app_id = string
resource_access = list(object({
id = string
type = string
}))
}))
default = [{
resource_app_id = "00000003-0000-0000-c000-000000000000"
resource_access = [{
id = "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
type = "Role"
}]
}]
}
resource "azuread_application" "bootstrap" {
name = "test"
type = "webapp/api"
group_membership_claims = "All"
dynamic "required_resource_access" {
for_each = var.required_resource_access
content {
resource_app_id = required_resource_access.value["resource_app_id"]
dynamic "resource_access" {
for_each = required_resource_access.value["resource_access"]
content {
id = resource_access.value["id"]
type = resource_access.value["type"]
}
}
}
}
}
And the plan shows:
Terraform will perform the following actions:
# azuread_application.bootstrap will be created
+ resource "azuread_application" "bootstrap" {
+ application_id = (known after apply)
+ available_to_other_tenants = false
+ group_membership_claims = "All"
+ homepage = (known after apply)
+ id = (known after apply)
+ identifier_uris = (known after apply)
+ name = "test"
+ oauth2_allow_implicit_flow = true
+ object_id = (known after apply)
+ owners = (known after apply)
+ public_client = (known after apply)
+ reply_urls = (known after apply)
+ type = "webapp/api"
+ oauth2_permissions {
+ admin_consent_description = (known after apply)
...
}
+ required_resource_access {
+ resource_app_id = "00000003-0000-0000-c000-000000000000"
+ resource_access {
+ id = "7ab1d382-f21e-4acd-a863-ba3e13f7da61"
+ type = "Role"
}
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
I removed a lot of your variables an some of the optional Arguments for azuread_application to keep the code as small as possible, but the same principle applies to your code, use lists on for_each or it will loop on the object properties.

Writing Corda custom query by concating two schema column values and compare?

We have Name schema contains,
FirstName : Rock
LastName : John
Prefix : Mr
MiddleName : ""
Suffix: "Jr"
We are creating some states, schema with the definition.
But Now Want to field the states with values. We need to filter the values like
(FirstName+LastName).equals("RockJohn").
We are trying to write the custom vault query.
Is there any way to achieve this?
In Java, you'd write something like:
FieldInfo firstNameField = getField("firstName", NameSchemaV1.PersistentName.class);
FieldInfo lastNameField = getField("lastName", NameSchemaV1.PersistentName.class);
CriteriaExpression firstNameIndex = Builder.equal(firstNameField, "Rock");
CriteriaExpression lastNameIndex = Builder.equal(lastNameField, "John");
QueryCriteria firstNameCriteria = new QueryCriteria.VaultCustomQueryCriteria(firstNameIndex);
QueryCriteria lastNameCriteria = new QueryCriteria.VaultCustomQueryCriteria(lastNameIndex);
QueryCriteria criteria = firstNameCriteria.and(lastNameCriteria);
Vault.Page<ContractState> results = getServiceHub().getVaultService().queryBy(NameState.class, criteria);
In Kotlin, you'd write something like:
val results = builder {
val firstNameIndex = NameSchemaV1.PersistentName::firstName.equal("Rock")
val lastNameIndex = NameSchemaV1.PersistentName::lastName.equal("John")
val firstNameCriteria = QueryCriteria.VaultCustomQueryCriteria(firstNameIndex)
val lastNameCriteria = QueryCriteria.VaultCustomQueryCriteria(lastNameIndex)
val criteria = firstNameCriteria.and(lastNameCriteria)
serviceHub.vaultService.queryBy(NameState::class.java, criteria)
}
You can use a Hibernate formula to create a dynamic/calculated property:
#Formula(value = " concat(first_name, last_name) ")
String fullName
Then treat it as a regular property/field in your queries

Resources