Mail application alike document soft deletion mechanism - sql-server

My question is a bit of a logical one. I hope my title is not misleading.
I'm working on a mail application like website where users can send or receive documents.
Documents are kept in a daabase table which holds attributes like Sender, Receiver, DeleteDate, DeleteuserId etc.
Let's look at this scenario.
A sends Document1 to B.
Document1 is at A's outbox and B's Inbox
A wants to delete it from the outbox
At this moment my deletion mechanism kicks in and sets the deletedate and deleteuserId of Document1 to date and Id of A respectively.
Problem is, now the document is logically deleted ( deletedate and deleteuserID are not null anymore) so both A and B can't see it because listing stored procedures don't allow "deleted" items to the list.
What kind of a logic should be implemented in order to let B see it and A don't ?

Not the best. but if you update the sender_id in the document table, then it will lost the connection with the document table. But if there is a some logic then you will create some other errors.

Related

How don't select the same row twice in two select cassandra queries?

I am working on a social networking project with cassandra. Users can subscribe to a profile and have access to the list of people who have subscribed to that same profile. My goal is to retrieve in a table called user_follows the list of people subscribed to a profile.
CREATE TABLE users_follows (to_id text, from_id text, followed_at timestamp, PRIMARY KEY(to_id, from_id))
The problem is that some profiles can have thousands of subscribers and I don't want to get them all at once. That's why I'd like to get the list in increments of 20 depending on how far down the user goes. My problem is that I can't see how to retrieve the other parts of the list after the first select because Cassandra always returns the same users.
SELECT * FROM users_follows where to_id = 'xxxxx'
A possible solution was to sort with a timestamp but in case I want to retrieve the list of people to whom a user is subscribed (the reverse query) this would not work. One solution would be to use materialized views but I'm not sure that it would be very optimal given the size of the table. Or to create a different table, one user_follows and another user_followers, but I don't think this is very recommended....

Outbound message on merging records

When I merge accounts, I want to trigger an outbound message. When I merge account, there is 1 record that is updated and and the other record that goes to recycle bin. I want to fetch Record Id of one that is merged with and the one that is updated. Is it possible with any conditions or do i need to code?
Yes you need to write a trigger for this although a rather simple one.
As stated in documentation merge doesn't trigger they own event instead delete and uppate events triggered.
From Documentation :
To determine which records were deleted as a result of a merge operation use the
MasterRecordId field in Trigger.old. When a record is deleted after losing a merge
operation, its MasterRecordId field is set to the ID of the winning record.
Link to full page

skype main.db - difference between Chats and Conversations

I've been dissecting Skype database main.db for a couple of days, and this is something which I haven't yet figured out. Naturally, this question will be very specifically for Skype main.db structure.(disclaimer)
It seems that all the necessary information that I need are in tables Conversations, Messages, Participants.
Message table contains actual log that has been said, the recipient(s), timestamp, and the convo_id foreign key(although not enforced) to connect to a Conversation which the message belongs to.
Conversation exists to hold the aggregates of Message and the Contacts that participate in.
Participants table works to a many-to-many connector table between the Conversations table and Contacts table.
What gets me are Chats and Chatmembers table. Chatmembers works to Chats what Participants table works to Conversations table; connecting Contacts and the conversations-or 'chats'.
What's in Chats is similar to Conversations except that it does not have any aggregate to Message table. It is impossible to map from Messages table to Chats table to which the message log(row of Messages table) belongs.
Chats and Conversations share a foreign key, Conversations table has a column named chat_dbid which joins to the Chats table. But there are rows in Conversations table which have a null chat_dbid field, and not all rows in Chats have id field which corresponds to chat_dbid field in Chats table.
The Chats table is still being updated and I recognize some of the chats-or conversations- I've had recently based on the timestamp and the members in it.
Does anyone know exactly what Chats table does? Or rather, what's the difference and justification for Chats table and Conversations table?
When I looked frantically for this I could find only one like that talked about main.db structure, and it wasn't very helpful.
According to the link Chats
Provides the chats in which the user participated.
and Conversations
Provides a list of the conversations in which the user participated.
What's their terminology about Chats and Conversations? How are they different?
It's been driving me crazy.
Yesterday I was also going through main.db table in skype. Below are my findings.
Conversations table uniquely identifies conversation with a particular contact(or a group contact you have created). Conversation entails all communication: chat messages, voice message, file transfers, calls that you do with a particular contact. Most of the tables have references to the entry in this table.
Messages table has convo__id,
Chats table has conv_dbid,
Transfers has convo_id and likewise.
Messages table: messages entry are not always chats. If an entry is chat then its chatname field is populated.
It seems that chats and messages has one to many relations. chat is a collection of messages maintained per some identifier(most probably day not sure.). "type=61" seems to be normal message: message typed by user. Other types seem to be auto generated messages for eg. msg you get if a call is disconnected.
Hope this helps.
It looks like Chats are redundant. Messages are grouped into chats as an after-thought, you can have several Chats inside one Conversation and then some messages outside any Chat. The rules for grouping are unclear, perhaps by time.
Grouping is done by setting chatname field of a bunch of messages to the same value. Chat names look like #SenderId/$TargetId;ChatId or #SenderId/ChatId for Chats over groupchat.
ChatIds don't seem to hold any particular meaning and can be different on different PCs.
Not every Chat gets an entry in Chats table: SELECT DISTINCT(chatname) FROM Messages gives a great many more entries than SELECT * FROM Chats. Not everything that goes into chatname is a name of chat from Chats. Sometimes it's a conversation id (== groupchat id or skypename).
Different Skype instances also group the same synchronized messages into Chats differently.
So basically Chats are not important, they group messages arbitrarily, they don't contain any key data about who sent what to whom.
This is how I understand other tables work:
Contacts - this is everyone whose skypename is mentioned in the database, even people you never knew about (which said something in the groupchat you were listening to at the time). is_permanent marks those in your contact list.
Conversations - this is a union of your actual contacts and groupchats you have ever had joined. This is what one should see as "contact list". If you need contacts you've never messages, add Contacts WHERE is_permanent=1. If you only want present contacts, filter by is_bookmarked or something like that.
There seems to be no duplicates and splits. One contact = one conversation, one groupchat = one conversation. If you're talking with a contact one on one and you add another party, previous messages remain in that contact's Conversation, and the following ones get their own Conversation.
Messages - this is all messages and events ever sent or received:
convo_id - always set, always references a conversation. This is how you identify to what contact / groupchat the messages was sent.
chatname - always set, sometimes references a chat from Chats, sometimes a chat which is not in Chats, sometimes a groupchat id or skypename from Conversations. Mostly this can be ignored, or you can group messages by this field visually.
author, from_name - who sent this message and their nick at the time, always set properly.
dialog_partner - very unreliable, different values for the same message on different PCs
participant_count - sometimes set, sometimes not, same as with dialog_partner: unreliable.
identities - mentions all skypenames related to the event, or sometimes doesn't. Rules are unclear, unreliable.

Any simple approaches for managing customer data change requests for global reference files?

For the first time, I am developing in an environment in which there is a central repository for a number of different industry standard reference data tables and many different customers who need to select records from these industry standard reference data tables to fill in foreign key information for their customer specific records.
Because these industry standard reference files are utilized by all customers, I want to reserve Create/Update/Delete access to these records for global product administrators. However, I would like to implement a (semi-)automated interface by which specific customers could request record additions, deletions or modifications to any of the industry standard reference files that are shared among all customers.
I know I need something like a "data change request" table specifying:
user id,
user request datetime,
request type (insert, modify, delete),
a user entered text explanation of the change request,
the user request's current status (pending, declined, completed),
admin resolution datetime,
admin id,
an admin entered text description of the resolution,
etc.
What I can't figure out is how to elegantly handle the fact that these data change requests could apply to dozens of different tables with differing table column definitions. I would like to give the customer users making these data change requests a convenient way to enter their proposed record additions/modifications directly into CRUD screens that look very much like the reference table CRUD screens they don't have write/delete permissions for (with an additional text explanation and perhaps request priority field). I would also like to give the global admins a tool that allows them to view all the outstanding data change requests for the users they oversee sorted by date requested or user/date requested. Upon selecting a data change request record off the list, the admin would be directed to another CRUD screen that would be populated with the fields the customer users requested for the new/modified industry standard reference table record along with customer's text explanation, the request status and the text resolution explanation field. At this point the admin could accept/edit/reject the requested change and if accepted the affected industry standard reference file would be automatically updated with the appropriate fields and the data change request record's status, text resolution explanation and resolution datetime would all also be appropriately updated.
However, I want to keep the actual production reference tables as simple as possible and free from these extraneous and typically null customer change request fields. I'd also like the data change request file to aggregate all data change requests across all the reference tables yet somehow "point to" the specific reference table and primary key in question for modification & deletion requests or the specific reference table and associated customer user entered field values in question for record creation requests.
Does anybody have any ideas of how to design something like this effectively? Is there a cleaner, simpler way I am missing?
Option 1
If preserving the base tables is important then I would create a "change details" table as a child to your change request table. I'm envisioning something like
ChangeID
TableName
TableKeyValue
FieldName
ProposedValue
Add/Change/Delete Indicator
So you'd have a row in this table for every proposed field change. The challenge in this scenario is maintaining the mapping of TableName and FieldName values to the actual tables and fields. If your database structure if fairly static then this may not be an issue.
Option 2
Add a ChangeID field to each of your base tables. When a change is proposed add a record to the base table with the ChangeID populated. So as an example if you have a Company table, for a single company you could have multiple records:
CompanyCode ChangeID CompanyName CompanyAddress
----------- -------- ----------- --------------
COMP1 My Company Boston <-- The "live" record
COMP1 1 New Name Boston <-- A proposed change
When the admin commits the change the existing live record is deleted or archived and the ChangeID value is removed from the proposed record making it the live record. It may be a little tricky to handle proposed deletions with this option. This option also has the potential for impacting performance of selecting live data for normal usage. However it does save you the hassle of maintaining a list of table names and field names somewhere in your code.
I'm sure others will have some opinions!

Entity Deletion Strategy

Say you have a ServiceCall database table that records down all the service calls made to you. Each of this record contains a many to one relationship to Customer record, where it stores which customer made the Service Call.
Ok, suppose the Customer has stop doing business with you and you do not need the Customer's record in your database. No longer need the Customer's name to appear in the dropdown list when you create a new ServiceCall record.
What do you do?
Do you allow the user to delete the Customer's record from the database?
Do you set a special column IsDeleted to true for that Customer's record, then make sure all dropdown list will not load all records that has IsDeleted set to true? Although this keeps the old records from breaking at innerjoins, it also prevents user from adding a new record with the same name as the old Customer, won't it?
Do you disallow deletion at all? Just allow to 'disable' it?
Any other strategies you used? I am guessing everyone have their way, I just need to see your opinions.
Of course the above is quite simplified, usually a ServiceCall record will link to many other entity tables. All of which will face the same problem when they are required to be deleted.
I prefer to set an IsDeleted flag, one of the benefits is you can still report on historical information (all teh data is still there).
As to the issue of not being able to insert another customer with the same name, this isn't a problem if you use an ID column (eg CustomerId) which is generally auto populated.
I agree with #Tetraneutron's answer.
Additionally, you can create a VIEW that lists only the active customers, to make it more convenient to populate drop-down lists and such.

Resources