How to represent unique attribute in Z-notation without quantifiers? - formal-methods

Full disclosure, this is for a university course. I don't expect an answer outright, but help would be appreciated.
I need to model an Item entity using Z-notation. This is the description:
Item: Every item has a name and a unique ID which can be used to uniquely describe the item. An item also has a price (positive float) and a category.
Part of the requirement is modelling these entities without quantifiers.
This is what I ended up with, but I'm not sure that it's correct:
Schema for Item
The idea being that the name is some combination of strings, the ID is a tuple of a positive integer and said name, and both the price and the category are mapped with total functions.
The first predicate is to ensure a positive price, the second is to ensure the uniqueness of the ID, i.e. reduce the domain to all integers that are not already assigned. I don't think this is correct, though.

The main issue with your approach is that you try to put information about the whole system (or part of it) into the description of a single item. E.g. you specified the price as a mapping from the id to a float - which is fine in principle - but you do not have such a function for each item.
There are many ways to specify this, I show two approaches:
You have two schemas: E.g. Item and Database
+-- Item -----
| id: ℕ
| name: String
| price: ℝ
| category: String
|----
| price ≥ 0
+----------
+-- Database -----
| items: ℕ +-> Item
|----------
This way you have the ID of each item moved from the item itself. When each item has also a field id, it would be complicated to state without quantifiers the fact that items should map an id to an item with the same id. Or when you just use a set of items it would be complicated to describe without quantifiers that two items must have distinct identifiers.
The uniqueness of the id for each item is guaranteed by items being a function.
Or just use several functions for each aspect of an item:
+-- Items -----
| ids: ℕ
| name: ids --> String
| price: ids --> ℝ
| category: ids --> String
+----------
But stating the fact that all prices must be non-negative without quantifiers would be hard. Maybe by replacing ℝ by { x:ℝ | x≥0}.
A general remark: Do you need compute with your IDs? Maybe you can introduce a type with [ID] instead. The same applies for the category (e.g. [CATEGORY]).
And is the name not just a single string? But I don't think it would be a set of (unordered) strings.

Related

How to pick transaction isolation levels?

I have a table in database that is responsible for storing ordered/reorderable lists. It has the following shape:
| id | listId | index | title | ... |
where id is primary key, listId is foreign key that identifies what list the item belongs to, title and other columns are contents of items. index property is responsible for position of item in list. It is an integer counter (starting with 0) that is unique in the scope of the list, but may repeat across lists. Example data:
| id | listId | index | title | ...
---------------------------------------------
| "item1" | "list1" | 0 | "title1" | ...
| "item2" | "list1" | 1 | "title2" | ...
| "item3" | "list1" | 2 | "title3" | ...
| "item4" | "list2" | 0 | "title4" | ...
| "item5" | "list2" | 1 | "title5" | ...
Users can create/delete items, move them inside the list or across lists.
To ensure consistency of indexes when running these operations, I do the following:
Create item:
Count items within this list
SELECT COUNT(DISTINCT "Item"."id") as "cnt"
FROM "item" "Item"
WHERE "Item"."listId" = ${listId}
Insert new item, with index set to count from step 1:
INSERT INTO "item"("id", "listId", "index", "title", ...)
VALUES (${id}, ${listId}, ${count}, ${title})
This way index grows with each item inserted into the list.
Move item:
Retrieve item's current listId and index:
SELECT "Item"."listId" AS "Item_listId", "Item"."index" AS "Item_index"
FROM "item" "Item"
WHERE "Item"."id" = ${id}
Change index of "shifted" items if necessary, so that order is consistent, e.g. given the item is moved forward, all items between its current position (exclusively) and its next position (inclusively) need to have their index decreased by 1:
UPDATE "item"
SET "index" = "index" - 1
WHERE "listId" = ${listId}
AND "index" BETWEEN ${sourceIndex + 1} AND ${destinationIndex}
I'll omit the variation with movement across lists because it is very similar.
Update the item itself:
UPDATE "item"
SET "index" = ${destinationIndex}
WHERE "id" = ${id}
Delete item:
Retrieve item's index and listId
Move all items in same list that are next to this item 1 step back, to remove the gap
UPDATE "item"
SET "index" = "index" - 1
WHERE "listId" = ${listId}
AND "index" > ${itemIndex}
Delete item:
DELETE FROM "item"
WHERE "id" = ${id}
Question is:
What transaction isolation levels should I provide for each of these operations? It is very important for me to keep index column consistent, no gaps and most importantly - no duplicates. Am I getting it right that create item operation is subject to phantom reads, because it counts items by some criteria, and it should be serializable? What about other operations?
Without knowing more about your specific application, the safest bet is indeed to use serializable as isolation level whenever you access that table but even that level may not be sufficient for your specific case.
A unique constraint on (listId, index) would prevent duplicates (what about the title? Can it be repeated in the same list?), some accurately crafted "watchdog" queries can further mitigate issues and database sequences or stored procedures can ensure that there are no gaps but truth is the mechanism itself seems fragile.
Knowing only so much of your specific problem, what you appear to have is a concurrency problem at user level in the sense that several users can access the same objects at the same time and make changes on them. Assuming this is your typical web-application with a stateless back-end (hence inherently distributed) this may carry a large amount of implications in terms of user experience reflecting on the architecture and even functional requirements. Say for example that user Foo moves item Car to List B which is currently being worked on by user Bar. It is then legit to assume that Bar will need to see item Car as soon as the operation is completed, but that will not happen unless there's some mechanism in place to immediately notify users of List B of the change. The more users you have working on the same set of lists, the worse it becomes even with notifications as you would have more and more of them up to the point where users see things changing all the time and just can't keep up with it.
There's a lot of assumptions anyone will make to provide you an answer. My own lead me to state that you probably need to revise the requirements for that application or ensure that management is aware of several limitations and that they accept them.
This type of problem is pretty common in distributed applications. Usually "locks" on certain sets of data are placed (either through database or shared memory pools) so that only one user can alter them at any given time or, alternatively, a workflow is provided to manage conflicting operations (much like versioning systems). When neither is done, a log of operations is kept to understand what happened and rectify problems later on should they be detected.
According to your constraints, you can create a unique index on two columns: listId,index can be defined as unique. That will avoid duplicates.
Additionally to avoid gaps I would recommend:
select listId, index, (select min(index) from Item i2 where listId = :listId and i2.index > i1.index) as nextIndex from Item i1 where nextIndex - index > 1 and listId = :listId
at the end of each transaction.
Together with transaction isolation level: "Repeatable Read" and rolling back and repeating the transaction if either the unique constraint fails, or the statement, I suggested, returned a record, this should meet your requirements.

sqlite variable and unknown number of entries in column

I am sure this question has been asked before, but I'm so new to SQL, I can't even combine the correct search terms to find an answer! So, apologies if this is a repetition.
The db I'm creating has to be created at run-time, then the data is entered after creation. Some fields will have a varying number of entries, but the number is unknown at creation time.
I'm struggling to come up with a db design to handle this variation.
As an (anonymised) example, please see below:
| salad_name | salad_type | salad_ingredients | salad_cost |
| apple | fruity | apple | cheap |
| unlikely | meaty | sausages, chorizo | expensive |
| normal | standard | leaves, cucumber, tomatoes | mid |
As you can see, the contents of "salad_ingredients" varies.
My thoughts were:
just enter a single, comma-separated string and separate at run-time. Seems hacky, and couldn't search by salad_ingredients!
have another table, for each salad, such as "apple_ingredients", which could have a varying number of rows for each ingredient. However, I can't do this, because I don't know the salad_name at creation time! :(
Have a separate salad_ingredients table, where each row is a salad_name, and there is an arbitrary number of ingredients fields, say 10, so you could have up to 10 ingredients. Again, seems slightly hacky, as I don't like to unused fields, and what happens if a super-complicated salad comes along?
Is there a solution that I've missed?
Thanks,
Dan
based on my experience the best solution is based on a normalized set of tables
table salads
id
salad_name
salad_type
salad_cost
.
table ingredients
id
name
and
table salad_ingredients
id
id_salad
id_ingredients
where id_salad is the corresponding if from salads
and id_ingredients is the corresponding if from ingredients
using proper join you can get (select) and filter (where) all the values you need

Need denormalized query from heirarchial table

I have a table(lets name it HEIRARCHY_TABLE ) in this format representing hierarchical data where a tree is stored in this format.
HEIRARCHY_TABLE (parent_name ,parent_id ,child_name ,child_id)
Sample Data in HEIRARCHY_TABLE:-
-------------------------------------------
parent_name |parent_id |child_name |child_id
--------------------------------------------
parent_1 | parent_1_id | leaf_node | leaf_node_id1
parent_2 | parent_2_id | parent_1 | parent_1_id
the above scenario is showing data for a case where parent_2->parent_1->leaf_node
where -> representing "is parent of " relation-ship.
I need to query this table and get a result like this for all leaf nodes.
Result:-
leaf_node | parent_1 | parent_2 | parent_3 |parent_4 | parent_5 |parent_6 | parent_7
and if for suppose a leaf node has only two parents then i require the rest of the parent values to be null.
i.e..,if it has only 5 parents.then parent_6 and parent_7 should be null.
Note :- the above table contains multiple trees.hence it contain multiple roots.I need data for all the trees available in this table in this format.the maximum level in all the trees is 7 only.
Google around for Common Table Expressions. What you are looking for, I think, is a recursive query. You are going to have to play some games to force the query to return nulls for parents that don't actually exist. [Check this.] (http://www.morganslibrary.org/reference/with.html)
The fastest query would be to use heirarchy IDs. then you can query against all or part of a tree using CONTAINS on the heirarchy id column.
Of course this assumes you are allowed to/can build this column.
For oracle, you can do Heirarchy Query. Not sure about its efficiency/demormalization factor. http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm

Core Data fetch request predicate filtering across one-to-one relationship

I have the following model graph:
+-----------+ +-----------+
| Container | | Group |
+-----------+ +-----------+
| groups |<-->>| container |
+-----------+ +-----------+
^ ^
| |
+-----------+ +-----------+ +-----------+ +---------+
| Owner | | ToyBox | | ToyType | | Item |
+-----------+ +-----------+ +-----------+ +---------+
| toyBox |<--->| owner | | items |<-->>| toyType |
+-----------+ +-----------+ +-----------+ +---------+
In a UITableView I am to display a list a list of Items. In this case I only want to show the items that belong to a particular owner. To do this I will use NSFetchedResultsController to display the items. This means that I need create an NSFetchRequest with an appropriate NSPredicate to give to the NSFetchedResultsController.
Attempting to use a keypath predicate causes an exception due to the parent entities. This appears to be an Apple bug or decision not to support. A radar has been filed. Additionally, I do not wish to flatten the entities.
So that left me with an attempt to do this with SUBQUERY() as follows:
NSFetchRequest *itemsFetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Item"];
NSPredicate *itemsPredicate = [NSPredicate predicateWithFormat:#"SUBQUERY(toyItem, $g, SUBQUERY($g.container, $c, SUBQUERY($c.owner, $o, $o = %#).#count > 0).#count > 0).#count > 0", ownerObject];
This results in the following exception:
Can't have a non-relationship collection element in a subquerySUBQUERY($c.owner, $o, $o == <MLMOOwner: ...
I realize that because the relationship is one to one between Owner and ToyBox that there isn't a collection returned and this is the problem. So my questions are:
1) Is there a way to force the return of a collection for to-one relationships in the subquery?
2) If not is there another way to go about creating this predicate for the fetch request?
Seems like it should be a lot simpler to do what you want. If you want all the items with a given owner, start with the owner and use a key path to get the associated items. You don't need a predicate. If you've got 10 jars of peanuts and you want to retrieve the peanuts in jar 2, you don't start with the set of all peanuts and then filter them according to their jar, right? You first get jar 2, and then you look at the peanuts it contains. So do this:
NSSet *groups = [ownerObject valueForKeyPath:#"toyBox.groups"];
That gives you all the groups owned by ownerObject. You can't just get all the items using a single key path because the Group entity doesn't have an items attribute. You could make life easier for yourself by giving Group an items accessor, even if it only returns an empty set. That would let you do this:
NSSet *items = [ownerObject valueForKeyPath:#"toyBox.groups.items"];
If you don't want to add an items attribute to Group, you'll have to filter the set groups from the first example to pick out just those objects that are ToyType objects. You can then use the key path #"items" on that set to get the list of items that you want.
You have to be a bit careful with entity inheritance. You've just seen how it can make fetching a little more complicated. It also has implications for the way your data is stored, namely that all instances of sub-entities are stored in the same table. So, if you have a dozen entities derived from Group (such as ToyType), all the instances of all those entities are stored together.

How do I create sql query for searching partial matches?

I have a set of items in db .Each item has a name and a description.I need to implement a search facility which takes a number of keywords and returns distinct items which have at least one of the keywords matching a word in the name or description.
for example
I have in the db ,three items
1.item1 :
name : magic marker
description: a writing device which makes erasable marks on whiteboard
2.item2:
name: pall mall cigarettes
description: cigarette named after a street in london
3.item3:
name: XPigment Liner
description: for writing and drawing
A search using keyword 'writing' should return magic marker and XPigment Liner
A search using keyword 'mall' should return the second item
I tried using the LIKE keyword and IN keyword separately ,..
For IN keyword to work,the query has to be
SELECT DISTINCT FROM mytable WHERE name IN ('pall mall cigarettes')
but
SELECT DISTINCT FROM mytable WHERE name IN ('mall')
will return 0 rows
I couldn't figure out how to make a query that accommodates both the name and description columns and allows partial word match..
Can somebody help?
update:
I created the table through hibernate and for the description field, used javax.persistence #Lob annotation.Using psql when I examined the table,It is shown
...
id | bigint | not null
description | text |
name | character varying(255) |
...
One of the records in the table is like,
id | description | name
21 | 133414 | magic marker
First of all, this approach won't scale in the large, you'll need a separate index from words to item (like an inverted index).
If your data is not large, you can do
SELECT DISTINCT(name) FROM mytable WHERE name LIKE '%mall%' OR description LIKE '%mall%'
using OR if you have multiple keywords.
This may work as well.
SELECT *
FROM myTable
WHERE CHARINDEX('mall', name) > 0
OR CHARINDEX('mall', description) > 0