I want to create State with unique id in database. There is my State code
data class SampleState(
val partyA: Party,
val partyB: Party,
val value: Int,
val id: String,
override val linearId: UniqueIdentifier = UniqueIdentifier(id),
val properties: LCProperties = LCProperties("ABC")) : LinearState {...}
When I commit two similar SampleState, there are two different State in database with two different linearId. So, There are anyone can talk me that how to ensure that the "id" of a object of SampleState in database is unique?
I used same code for catch this case in Flows and Contracts like
val results = builder {
val quantityIndex = SampleSchemaV1.PersistentSample::id.equal(id);
val customCriteria1 = QueryCriteria.VaultCustomQueryCriteria(quantityIndex)
val criteria = generalCriteria.and(customCriteria1);
serviceHub.vaultService.queryBy<SampleState>(criteria)
}
if(results.states.count() > 0)
throw IllegalArgumentException("id $id is exist")
However, it do not work with two commit Sample State Transaction in a near similar time even that in 1s (commit Transaction 1, and after 1 second, commit Transaction 2)
In your state code, it is this line:
override val linearId: UniqueIdentifier = UniqueIdentifier(id)
That creates a unique id for you. The id that you are passing into UniqueIdentifier binds the unique id that is generated to your id. However all equality and comparison are based on the unique ID only.
Take a look at UniqueIdentifier.kt in the source code and you'll see this is the underlying code:
data class UniqueIdentifier(val externalId: String? = null, val id: UUID = UUID.randomUUID()) : Comparable<UniqueIdentifier> {
override fun toString(): String = if (externalId != null) "${externalId}_$id" else id.toString()
This is a good post about how good Java's randomUUID is in ensuring an id is unique
You can also read more about UniqueIdentifier here
Related
with RealmDB object how to write multiple keys query ?
Schema Part:
StudentSchemaNames.student_data = { classID: int, students:
Students[], noOfPresence: int, noOfabsence: int, noOfLeft: int } ;
StudentScehmaNames.students = {studentid:int, studentfirstName:
string:, studentlastName:string}
I am having an object like;
studentDetails = [{"classID": "001", "students": [Array],
"noOfPresence": 30, "noOfabsence": 2, "noOfLeft": 9}];
currently I am fetching details basic on studentId= 001 ;
studentDetails = await RealmDB.get(StudentSchemaNames.student_DATA,
studentId="${studentId}" AND 'noOfPresence');
here student ID property is passed with value and noOfPresence only property name and no value in query to be executed.
but I wanted to write query like ;
Scenario1: Fetch data basis on student ID with value and NoOfPresence only Property
Scenario2: Fetch data basis on students property only with student id value
Scenario3: Fetch data basis on class Property only with student id value
help me out to write queries for above scenario with RealmDB. Thank you in advance
I have a table as : AdvgCountries which has two columns
a. CountryId (String) (Parition Key)
b. CountryName(String) Sort Key
While creating the table , I created with only Partition Key and then later added a Global Secondary Index with Index name as:
CountryName-index
Type : GSI
Partition key : CountryId
Sort Key : CountryName
I am able to retrieve CountryName based upon CountryId but unable to retrieve CountryId based upon CountryName. Based upon my reading I found that there are options to do this by providing indexname but I get the following error:
botocore.exceptions.ClientError: An error occurred
(ValidationException) when calling the Query operation: Query
condition missed key schema element: CountryId
import boto3
import json
import os
from boto3.dynamodb.conditions import Key, Attr
def query_bycountryname(pCountryname, dynamodb=None):
if not dynamodb:
dynamodb = boto3.resource('dynamodb', endpoint_url="https://dynamodb.us-east-1.amazonaws.com")
table = dynamodb.Table('AdvgCountires')
print(f"table")
attributes = table.query(
IndexName="CountryName-index",
KeyConditionExpression=Key('CountryName').eq(pCountryname),
)
if 'Items' in attributes and len(attributes['Items']) == 1:
attributes = attributes['Items'][0]
print(f"before return")
return attributes
if __name__ == '__main__':
CountryName = "India"
print(f"Data for {CountryName}")
countries = query_bycountryname(CountryName)
for country in countries:
print(country['CountryId'], ":", country['CountryName'])
Any help is appreciated.
You can't be able to fetch primary key value based on sort key. DynamoDB does not work like this.
In Dynamodb, each item’s location is determined by the hash value of
its partition key.
The Query operation in Amazon DynamoDB finds items based on primary
key values.
KeyConditionExpression are used to write conditional statements by
using comparison operators that evaluate against a key and limit the
items returned. In other words, you can use special operators to
include, exclude, and match items by their sort key values.
I am developing a complaint management in which I have to generate unique serial number for each complaint like 00001/20 {Serial number/year}.
I am using repository pattern and i am generating this complaint number using the following code snippet but problem is if two user try to lodge a complaint at the same time it will generate a same complaint no and that thrown an error as I am keeping a serial number in a separate table which is also mentioned below for reference. Let me know the best way to achieve this
int serialNo = repository.serialNo.Find(c => c.Year == DateTime.Now.Year).FirstOrDefault().TicketCounter;
string complaintNo = string.Format("{0}", serialNo.ToString().PadLeft(5, '0'));
model.Id = repository.complaintRepo.GetMaxPK(c => c.Id);
I am using repository pattern.
I guess, one of the solutions is to setup the table so that it generates required ID automatically on every new row. This ensures that the ID is always unique.
CREATE SEQUENCE MySequence
AS int
START WITH 1
INCREMENT BY 1;
CREATE TABLE Complaint
(
Id char(8) CONSTRAINT [DF_Complaint_ID]
DEFAULT FORMAT((NEXT VALUE FOR MySequence), '0000#')
+'/'+RIGHT(YEAR(GETDATE()),2),
Foo int,
Bar int,
CONSTRAINT [PK_MyTable] PRIMARY KEY (Id)
);
Demo: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=18a5d0fec80a3985e30cef687d3c8e49
So there will be no need to assign the id manually and your code could look like
var c = repository.Insert(new model
{
Foo = ...
Bar = ...,
...
});
repository.Save();
// you can get id after inserting data in the database
string id = c.Id;
I wrote query like below. I am able to retrieve data fromtime and totime. My problem is for every minute they are 30 records. I would like to get help to get the first record for every one hour and 24 records for one day and I need this for 30 days.
var config = new QueryRequest
{
TableName = "dfgfdgdfg",
KeyConditionExpression = "id= :id AND plctime BETWEEN :fromtime AND :totime",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{
":serialNumber", new AttributeValue {S = id}
},
{
":fromtime", new AttributeValue {S = fromtime }
},
{
":totime", new AttributeValue {S = totime }
}
},
};
return await _dynamoClient.QueryAsync(config);
In addition to storing your record as is, you could consider inserting another record that looks like this :
{
pk : "DailyMarker_" + DateTime.Now.ToString("yyMMdd"), // partition key
sk : "HourlyMarker_" + DateTime.Now.ToString("yyMMddhh") // range key
record: <your entire record>
}
pk and sk would be of the structure DailyMarker_201911 and HourlyMarker_2019112101. Basically the part after the underscore acts as a date/time stamp with only the granularity you are interested in.
While inserting a marker record, you can add precondition checks, which, if they fail, will prevent the insertion from taking place (see PutItem -> ConditionExpression. This operation throws an exception with most SDKs if the condition evaluates to false, so you want to handle that exception.
At this point only the first record per hour is being inserted into this PK/SK combination, and all SKs for one day end up under the same PK
To query for different ranges, you will have to perform some calculations in your application code to determine the start and end buckets (pk and sk) that you want to query. While you will need to make one call per pk you are interested in, the range key can be queried using range queries
You could also switch the pk to be monthly instead of daily, so that will reduce the number of PKs to query while increasing the potential for imbalanced keys (aka. hot keys)
How to translate this snippet of executable pseudo code into ABAP?
phone_numbers = {
'hans': '++498912345',
'peter': '++492169837',
'alice': '++6720915',
}
# access
print (phone_numbers['hans'])
# add
phone_numbers['bernd']='++3912345'
# update
phone_numbers['bernd']='++123456'
if 'alice' in phone_numbers:
print('Yes, alice is known')
# all entries
for name, number in phone_numbers.items():
print(name, number)
Modern ABAP is possible up to 752, less chars, more upvotes :-)
P.S. BTW, up to now no one has added abap to pleac (Programming Language Examples Alike Cookbook)
Well, how about the following solution?
REPORT ZZZ.
TYPES: BEGIN OF t_phone_number,
name TYPE char40,
number TYPE char40,
END OF t_phone_number.
DATA: gt_phone_number TYPE HASHED TABLE OF t_phone_number WITH UNIQUE KEY name.
START-OF-SELECTION.
gt_phone_number = VALUE #(
( name = 'hans' number = '++498912345' )
( name = 'peter' number = '++492169837' )
( name = 'alice' number = '++6720915' )
).
* access
WRITE / gt_phone_number[ name = 'hans' ]-number.
* add
gt_phone_number = VALUE #( BASE gt_phone_number ( name = 'bernd' number = '++3912345' ) ).
* update
MODIFY TABLE gt_phone_number FROM VALUE #( name = 'bernd' number = '++123456' ).
IF line_exists( gt_phone_number[ name = 'alice' ] ).
WRITE / 'Yes, Alice is known.'.
ENDIF.
* all entries
LOOP AT gt_phone_number ASSIGNING FIELD-SYMBOL(<g_phone_number>).
WRITE: /, <g_phone_number>-name, <g_phone_number>-number.
ENDLOOP.
#Jagger's answer is great, but #guettli asked for shorter syntax. So just for completeness, there is of course always the possibility to wrap this in a class:
CLASS dictionary DEFINITION.
PUBLIC SECTION.
TYPES:
BEGIN OF row_type,
key TYPE string,
data TYPE string,
END OF row_type.
TYPES hashed_map_type TYPE HASHED TABLE OF row_type WITH UNIQUE KEY key.
METHODS put
IMPORTING
key TYPE string
data TYPE string.
METHODS get
IMPORTING
key TYPE string
RETURNING
VALUE(result) TYPE string.
METHODS get_all
RETURNING
VALUE(result) TYPE hashed_map_type.
METHODS contains
IMPORTING
key TYPE string
RETURNING
VALUE(result) TYPE abap_bool.
PRIVATE SECTION.
DATA map TYPE hashed_map_type.
ENDCLASS.
CLASS dictionary IMPLEMENTATION.
METHOD put.
READ TABLE map REFERENCE INTO DATA(row) WITH TABLE KEY key = key.
IF sy-subrc = 0.
row->*-data = data.
ELSE.
INSERT VALUE #( key = key
data = data )
INTO TABLE map.
ENDIF.
ENDMETHOD.
METHOD get.
result = map[ key = key ]-data.
ENDMETHOD.
METHOD get_all.
INSERT LINES OF map INTO TABLE result.
ENDMETHOD.
METHOD contains.
result = xsdbool( line_exists( map[ key = key ] ) ).
ENDMETHOD.
ENDCLASS.
Leading to:
DATA(phone_numbers) = NEW dictionary( ).
phone_numbers->put( key = 'hans' data = '++498912345' ).
phone_numbers->put( key = 'peter' data = '++492169837' ).
phone_numbers->put( key = 'alice' data = '++6720915' ).
" access
WRITE phone_numbers->get( 'hans' ).
" add
phone_numbers->put( key = 'bernd' data = '++3912345' ).
" update
phone_numbers->put( key = 'bernd' data = '++123456' ).
IF phone_numbers->contains( 'alice' ).
WRITE 'Yes, alice is known'.
ENDIF.
" all entries
LOOP AT phone_numbers->get_all( ) INTO DATA(row).
WRITE: / row-key, row-data.
ENDLOOP.
People rarely do this in ABAP because internal tables are so versatile and powerful. From my personal point of view, I'd like to see people build more custom data structures. Implementation details like HASHED or SORTED, see discussion in #Jagger's answer, are hidden away in a natural way when doing this.