Opa : insert new element to the Database - database

I'm in OPA for some days now and I really start to like it. I'm attending the first year of computer science and we make some database class the next year-
The little I know about Databases are from php, I have used MySQL with php and SQLlite with c++. But this type of database is a bit different from what I've seen.
I have followed the guide about database in OPA http://doc.opalang.org/manual/Hello--database but I have a question:
In the guide we declare a new Database:
type user_status = {regular} or {premium} or {admin}
type user_id = int
type user = { user_id id, string name, int age, user_status status }
database users {
user /all[{id}]
/all[_]/status = { regular }
}
We learn how to read this database and make some query to this database with Maps, but how do I add a new element? I was testing a bit:
/users/all[{id:0}]/name<-getusername;
but id should be auto increment, from the little I know.
Thanks everyone for the help =D
I really want to get in OPA, the little I have make is really impressive!

mongoDB and auto-increment
With mongoDB (the default Opa database) there is no auto-increment (like in SQL), for scalability reason.
But if you really need one, you can use a counter to create this feature yourself:
database users {
user /all[{id}]
int /fresh_key
/all[_]/status = { regular }
}
And increment the key each time you use it: /users/fresh_key++
Random fresh key
You can also generate a random id, for example with something like Random.string(6)
Read this thread to learn more about this technique: http://lists.owasp.org/pipermail/opa/2012-April/001052.html
User defined unique key
But if you are dealing with users, maybe you already have a unique key: what about using "login" or "email" as the unique key?

You can also use Date.in_milliseconds(Date.now_gmt()) for a more unique id, maybe concatenated with the user id

Related

How to Create a Currency and Inventory System in Discord.js

So I've been trying to make a currency system and an inventory system for my Discord bot for the past few days. However, I can't seem to make any progress at all. I've tried using sequelize and better-sqlite3 (which is what I'm currently using), all with no success.
const table = sql.prepare("SELECT count(*) FROM sqlite_master WHERE type ='table' AND name = 'balance';").get();
if (table["count(*)"] === 0) {
console.log("creating table...");
sql.prepare("CREATE TABLE scores (id TEXT PRIMARY KEY, user TEXT, guild TEXT, money INTEGER);").run();
sql.prepare("CREATE UNIQUE INDEX idx_scores_id ON scores (id);").run();
sql.pragma("synchronous = 1");
sql.pragma("journal_mode = wal");
}
client.getScore = sql.prepare("SELECT * FROM balance WHERE user = ? AND guild = ?");
client.setScore = sql.prepare("INSERT OR REPLACE INTO money (id, user, guild, money) VALUES (#id, #user, #guild, #money);");
The above code results in this error:
(node:13036) UnhandledPromiseRejectionWarning: SqliteError: table scores already exists
I don't have that much knowledge on stuff like this since there is so little material out there for me to refer to.
This is a bad approach to validate tables. You should use IF NOT EXISTS instead. See this question for reference:
From http://www.sqlite.org/lang_createtable.html:
CREATE TABLE IF NOT EXISTS some_table (id INTEGER PRIMARY KEY AUTOINCREMENT, ...);
You can also use IF NOT EXISTS for your index.
In the future I recommend focusing on the specific technology you're having issues with when researching and asking questions. There is in fact plenty of material out there about proper usage patterns for sqlite - but you have to search and ask specifically for sqlite.
In this question, for example, you ask about making a currency and inventory system in discord.js, but there is no discord.js code here, the error is a sqlite error, and searching for "how to create table only if it doesn't exist sqlite" would have brought you to the links above. In short, search for the specific technology you're using, not for the whole project.
That being said, there is also an "official unofficial" resource on creating a currency system with discord.js here: https://discordjs.guide/sequelize/currency.html - but it uses sequelize, so you may not find it as helpful.

Common strategy in handling concurrent global 'inventory' updates

To give a simplified example:
I have a database with one table: names, which has 1 million records each containing a common boy or girl's name, and more added every day.
I have an application server that takes as input an http request from parents using my website 'Name Chooser' . With each request, I need to pick up a name from the db and return it, and then NOT give that name to another parent. The server is concurrent so can handle a high volume of requests, and yet have to respect "unique name per request" and still be high available.
What are the major components and strategies for an architecture of this use case?
From what I understand, you have two operations: Adding a name and Choosing a name.
I have couple of questions:
Qustion 1: Do parents choose names only or do they also add names?
Question 2 If they add names, doest that mean that when a name is added it should also be marked as already chosen?
Assuming that you don't want to make all name selection requests to wait for one another (by locking of queueing them):
One solution to resolve concurrency in case of choosing a name only is to use Optimistic offline lock.
The most common implementation to this is to add a version field to your table and increment this version when you mark a name as chosen. You will need DB support for this, but most databases offer a mechanism for this. MongoDB adds a version field to the documents by default. For a RDBMS (like SQL) you have to add this field yourself.
You havent specified what technology you are using, so I will give an example using pseudo code for an SQL DB. For MongoDB you can check how the DB makes these checks for you.
NameRecord {
id,
name,
parentID,
version,
isChosen,
function chooseForParent(parentID) {
if(this.isChosen){
throw Error/Exception;
}
this.parentID = parentID
this.isChosen = true;
this.version++;
}
}
NameRecordRepository {
function getByName(name) { ... }
function save(record) {
var oldVersion = record.version - 1;
var query = "UPDATE records SET .....
WHERE id = {record.id} AND version = {oldVersion}";
var rowsCount = db.execute(query);
if(rowsCount == 0) {
throw ConcurrencyViolation
}
}
}
// somewhere else in an object or module or whatever...
function chooseName(parentID, name) {
var record = NameRecordRepository.getByName(name);
record.chooseForParent(parentID);
NameRecordRepository.save(record);
}
Before whis object is saved to the DB a version comparison must be performed. SQL provides a way to execute a query based on some condition and return the row count of affected rows. In our case we check if the version in the Database is the same as the old one before update. If it's not, that means that someone else has updated the record.
In this simple case you can even remove the version field and use the isChosen flag in your SQL query like this:
var query = "UPDATE records SET .....
WHERE id = {record.id} AND isChosend = false";
When adding a new name to the database you will need a Unique constrant that will solve concurrenty issues.

Python 3.3.2 - How to Set Out a Small Database?

I am creating a small database for 'trial', per se. I have tried a few setting outs ([{key: value}, {key: value}]. But, I need a solution that can be called by an ID (12345), a name (Rob Alsod), an area (A4 (Like an apartment building)), or a job (Manager, Administrator, etc). So, something like a dictionary (which can only be called by one key) will not work. I tried making a 'Person' class, but I need a way to easily keep track of the classes, and also to assign them easily. For example,
for whatever in whatever:
what = Person(name = 'Rob Alsod', id = 12345, job = 'Admin', area = 'A1') # What can I make this iterate with? (Badly formed question)
My point is, as it loops through, I cannot assign it to the same thing again and again.
Could someone try to make sense of what I am saying, and suggest a way to format my database?
You could easily use SQLAlchemy with SQLite. SQL queries are only a few lines of code away:
from sqlalchemy import *
db = create_engine('sqlite:///people.db')
metadata = MetaData()
user = Table('people', metadata,
Column('ID', Integer, primary_key = True),
Column('name', String(16), nullable = False),
Column('area', String(16)),
Column('job', String(60))
)
After that it is easy connection = db.connect(); result = connection.execute("select ID from people")
On Linux, pip and apt-get make the install a breeze as well.
HTH, Phil
If you want small database for storing any objects identified by key you can use shelve module:
http://docs.python.org/3.2/library/shelve.html

Is there any way to do a Insert or Update / Merge / Upsert in LLBLGen

I'd like to do an upmerge using LLBLGen without first fetching then saving the entity.
I already found the possibility to update without fetching the entity first, but then I have to know it is already there.
Updating entries would be about as often as inserting a new entry.
Is there a possibility to do this in one step?
Would it make sense to do it in one step?
Facts:
LLBLgen Pro 2.6
SQL Server 2008 R2
.NET 3.5 SP1
I know I'm a little late for this, but As I remember working with LLBLGenPro, it is totally possible and one of its beauties is everithing is possible!
I don't have my samples, but I'm pretty sure you there is a method named UpdateEntitiesDirectly that can be used like this:
// suppose we have Product and Order Entities
using (var daa = new DataAccessAdapter())
{
int numberOfUpdatedEntities =
daa.UpdateEntitiesDirectly(OrderFields.ProductId == 23 && OrderFields.Date > DateTime.Now.AddDays(-2));
}
When using LLBLGenPro we were able to do pretty everything that is possible with an ORM framework, it's just great!
It also has a method to do a batch delete called DeleteEntitiesDirectly that may be usefull in scenarios that you need to delete an etity and replace it with another one.
Hope this is helpful.
I think you can achieve what you're looking for by using EntityCollection. First fetch the entities you want to update by FetchEntityCollection method of DataAccessAdapter then, change anything you want in that collection, insert new entities to it and save it using DataAccessAdapter, SaveCollection method. this way existing entities would be updated and new ones would be inserted to the Database. For example in a product order senario in which you want to manipulate orders of a specified product then you can use something like this:
int productId = 23;
var orders = new EntityCollection<OrderEntity>();
using (DataAccessAdapter daa = new DataAccessAdapter())
{
daa.FetchEntityCollection(orders, new RelationPredicateBucket(OrderFields.ProductId == productId))
foreach(var order in orders)
{
order.State = 1;
}
OrderEntity newOrder = new OrderEntity();
newOrder.ProductId == productId;
newOrder.State = 0;
orders.Add(newOrder);
daa.SaveEntityCollection(orders);
}
As far as I know, this is not possible, and could not be possible.
If you were to just call adapter.Save(entity) on an entity that was not fetched, the framework would assume it was new. If you think about it, how could the framework know whether to emit an UPDATE or an INSERT statement? No matter what, something somewhere would have to query the database to see if the row exists.
It would not be too difficult to create something that did this more or less automatically for single entity (non-recursive) saves. The steps would be something like:
Create a new entity and set it's fields.
Attempt to fetch an entity of the same type using the PK or a unique constraint (there are other options as well, but none as uniform)
If the fetch fails, just save the new entity (INSERT)
If the fetch succeeds, map the fields of the created entity to the fields of the fetched entity.
Save the fetched entity (UPDATE).

What is the preferred way to set foreign relationships for an entity?

Product product = new Product() {
Category = category
};
_session.CommitChanges();
vs.
Product product = new Product() {
Category.ID = category.ID
};
_session.CommitChanges();
What is the difference? Which one to use? Both seem to be valid and get correctly saved in the database.
Always use the first version. This will make sure all the relations are in a state they should be , because the keys and stuff are assigned and managed by the RelationshipManager.
I just pass Category.ID.
When the query is executed against the database the only information that is passed to Product is the Category ID, that is, this is the info that will be stored in DB (in each Product row).
Behind the curtains, the engine knows the fields necessary to generate the SQL insert command, in this case, only Category.ID is necessary when saving the Product. That's why no matter what option you choose, the save operation always succeeds.

Resources