I have a simple User schema in mongoDB for my Flask server. I am using mongoengine to work with the database. The schema is as follows:
class User(Document):
username = StringField(unique=True, requireed=True)
email = EmailField(unique=True)
password = StringField(required=True)
creditCount = IntField(default=0, min_value=0, max_value=None)
date_created = DateTimeField(default=datetime.utcnow)
def json(self):
user_dict = {
"username": self.username,
"email": self.email,
"creditCount": self.creditCount,
}
return json.dumps(user_dict)
meta = {
"indexes": ["username"], # index based on username
"ordering": ["-date_created"], # order in decending order
}
When I try to decrement the creditCount of a user, I get an error saying the integer value is too small. I have confirmed that the user has 10 credits and they only need to have 1 credit for the code to work. The code I am using is as follows:
try:
user = User.objects(username=request.args["username"]).get()
print(user.creditCount)
except DoesNotExist:
return "That user does not exist"
if user.creditCount == 0:
return "You do not have enough credits to search for a doggo."
print("credits: " + str(user.creditCount)) #This is where I'm confirming the user has enough credits through the terminal
if os.path.isfile(filePath):
user.update(dec__creditCount=1)
return send_file(filePath)
I'm not entirely sure what the issue could be since I am validating that the user has more than one credit and also printing their credits to the terminal and they are over one. I am also able to increment the credit count with inc__creditCount=1.
Thanks!
Brad
There is an open ticket about this bug, see
https://github.com/MongoEngine/mongoengine/issues/2339
i am trying to make a game where players create their own buildings and can then save them for other players to see and play on. However, roblox doesn't let me store all the data needed for the whole creation(there are several properties for each brick)
All i get is this error code:
104: Cannot store Array in DataStore
any help would be greatly appreciated!
I'm not sure if this is the best method, but it's my attempt. Below is an example of a table, you can use tables to store several values. I think you can use HttpService's JSONEncode function to convert tables into strings (which hopefully can be saved more efficiently)
JSONEncode (putting brick's data into a string, which you can save into the DataStore
local HttpService = game:GetService("HttpService")
-- this is an example of what we'll convert into a json string
local exampleBrick = {
["Size"] = Vector3.new(3,3,3),
["Position"] = Vector3.new(0,1.5,0),
["BrickColor"] = BrickColor.new("White")
["Material"] = "Concrete"
}
local brickJSON = HttpService:JSONEncode(exampleBrick)
print(brickJSON)
-- when printed, you'll get something like
-- { "Size": Vector3.new(3,3,3), "Position": Vector3.new(0,1.5,0), "BrickColor": BrickColor.new("White"), "Material": "Concrete"}
-- if you want to refer to this string in a script, surround it with two square brackets ([[) e.g. [[{"Size": Vector3.new(3,3,3)... }]]
JSONDecode (reading the string and converting it back into a brick)
local HttpService = game:GetService("HttpService")
local brickJSON = [[ {"Size": Vector3.new(3,3,3), "Position": Vector3.new(0,1.5,0), "BrickColor": BrickColor.new("White"), "Material": "Concrete"} ]]
function createBrick(tab)
local brick = Instance.new("Part")
brick.Parent = <insert parent here>
brick.Size = tab[1]
brick.Position= tab[2]
brick.BrickColor= tab[3]
brick.Material= tab[4]
end
local brickData = HttpService:JSONDecode(brickJSON)
createBrick(brickData) --this line actually spawns the brick
The function can also be wrapped in a pcall if you want to account for any possible datastore errors.
Encoding a whole model into a string
Say your player's 'building' is a model, you can use the above encode script to convert all parts inside a model into a json string to save.
local HttpService = game:GetService("HttpService")
local StuffWeWantToSave = {}
function getPartData(part)
return( {part.Size,part.Position,part.BrickColor,part.Material} )
end
local model = workspace.Building --change this to what the model is
local modelTable = model:Descendants()
for i,v in pairs(modelTable) do
if v:IsA("Part") or v:IsA("WedgePart") then
table.insert(StuffWeWantToSave, HttpService:JSONEncode(getPartData(modelTable[v])))
end
end
Decoding a string into a whole model
This will probably occur when the server is loading a player's data.
local HttpService = game:GetService("HttpService")
local SavedStuff = game:GetService("DataStoreService"):GetDataStore("blabla") --I don't know how you save your data, so you'll need to adjust this and the rest of the scripts (as long as you've saved the string somewhere in the player's DataStore)
function createBrick(tab)
local brick = Instance.new("Part")
brick.Parent = <insert parent here>
brick.Size = tab[1]
brick.Position= tab[2]
brick.BrickColor= tab[3]
brick.Material= tab[4]
end
local model = Instance.new("Model") --if you already have 'bases' for the players to load their stuff in, remove this instance.new
model.Parent = workspace
for i,v in pairs(SavedStuff) do
if v[1] ~= nil then
CreateBrick(v)
end
end
FilteringEnabled
If your game uses filteringenabled, make sure that only the server handles saving and loading data!! (you probably already knew that) If you want the player to save by clicking a gui button, make the gui button fire a RemoteFunction that sends their base's data to the server to convert it to a string.
BTW I'm not that good at scripting so I've probably made a mistake somehwere.. good luck though
Crabway's answer is correct in that the HttpService's JSONEncode and JSONDecode methods are the way to go about tackling this problem. As it says on the developer reference page for the DataStoreService, Data is ... saved as a string in data stores, regardless of its initial type. (https://developer.roblox.com/articles/Datastore-Errors.) This explains the error you received, as you cannot simply push a table to the data store; instead, you must first encode a table's data into a string using JSONEncode.
While I agree with much of Crabway's answer, I believe the function createBrick would not behave as intended. Consider the following trivial example:
httpService = game:GetService("HttpService")
t = {
hello = 1,
goodbye = 2
}
s = httpService:JSONEncode(t)
print(s)
> {"goodbye":2,"hello":1}
u = httpService:JSONDecode(s)
for k, v in pairs(u) do print(k, v) end
> hello 1
> goodbye 2
As you can see, the table returned by JSONDecode, like the original, uses strings as keys rather than numeric indices. Therefore, createBrick should be written something like this:
function createBrick(t)
local brick = Instance.new("Part")
brick.Size = t.Size
brick.Position = t.Position
brick.BrickColor = t.BrickColor
brick.Material = t.Material
-- FIXME: set any other necessary properties.
-- NOTE: try to set parent last for optimization reasons.
brick.Parent = t.Parent
return brick
end
As for encoding a model, calling GetChildren would produce a table of the model's children, which you could then loop through and encode the properties of everything within. Note that in Crabway's answer, he only accounts for Parts and WedgeParts. You should account for all parts using object:IsA("BasePart") and also check for unions with object:IsA("UnionOperation"). The following is a very basic example in which I do not store the encoded data; rather, I am just trying to show how to check the necessary cases.
function encodeModel(model)
local children = model:GetChildren()
for _, child in ipairs(children) do
if ((child:IsA("BasePart")) or (child:IsA("UnionOperation"))) then
-- FIXME: encode child
else if (child:IsA("Model")) then
-- FIXME: using recursion, loop through the sub-model's children.
end
end
return
end
For userdata, such as Vector3s or BrickColors, you will probably want to convert those to strings when you go to encode them with JSONEncode.
-- Example: part with "Brick red" BrickColor.
color = tostring(part.BrickColor)
print(string.format("%q", color))
> "Bright red"
I suggest what #Crabway said, use HttpService.
local httpService = game:GetService("HttpService")
print(httpService:JSONEncode({a = "b", b = "c"}) -- {"a":"b","b":"c"}
But if you have any UserData values such as Vector3s, CFrames, Color3s, BrickColors and Enum items, then use this library by Defaultio. It's actually pretty nice.
local library = require(workspace:WaitForChild("JSONWithUserdata"))
library:Encode({Vector3.new(0, 0, 0)})
If you want a little documentation, then look at the first comment in the script:
-- Defaultio
--[[
This module adds support for encoding userdata values to JSON strings.
It also supports lists which skip indices, such as {[1] = "a", [2] = "b", [4] = "c"}
Userdata support is implemented by replacing userdata types with a new table, with keys _T and _V:
_T = userdata type enum (index in the supportedUserdataTypes list)
_V = a value or table representing the value
Follow the examples bellow to add suppport for additional userdata types.
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Usage example:
local myTable = {CFrame.new(), BrickColor.Random(), 4, "String", Enum.Material.CorrodedMetal}
local jsonModule = require(PATH_TO_MODULE)
local jsonString = jsonModule:Encode(myTable)
local decodedTable = jsonModule:Decode(jsonString)
--]]
I have been able to link PostgreSQL to java. I have been able to display all the records in the table, however I unable to perform delete operation.
Here is my code:
con = DriverManager.getConnection(url, user, password);
String stm = "DELETE FROM hostdetails WHERE MAC = 'kzhdf'";
pst = con.prepareStatement(stm);
pst.executeUpdate();
Please note that MAC is a string field and is written in capital letters. This field does exist in the table.
The error that I am getting:
SEVERE: ERROR: column "mac" does not exist
When it comes to Postgresql and entity names (Tables, Columns, etc.) with UPPER CASE letters, you need to "escape" the word by placing it in "". Please refer to the documentation on this particular subject. So, your example would be written like this:
String stm = "DELETE FROM hostdetails WHERE \"MAC\" = 'kzhdf'";
On a side note, considering you are using prepared statements, you should not be setting the value directly in your SQL statement.
con = DriverManager.getConnection(url, user, password);
String stm = "DELETE FROM hostdetails WHERE \"MAC\" = ?";
pst = con.prepareStatement(stm);
pst.setString(1, "kzhdf");
pst.executeUpdate();
I've been trying to give myself a crash course in Yesod, but I can't seem to figure out what I'm doing wrong here. It's likely a conceptual failing, but I've more-or-less copy-pasted the code available on various short introductions to HashDB in an attempt to make a hashed DB authentication system, but no dice.
Foundation.hs:136:23:
Couldn't match type ‘AuthEntity App’ with ‘User’
In the expression: getAuthIdHashDB AuthR (Just . UniqueUser) creds
In an equation for ‘getAuthId’:
getAuthId creds = getAuthIdHashDB AuthR (Just . UniqueUser) creds
In the instance declaration for ‘YesodAuth App’
From each segment of code that's relevant:
config/models:
User
name Text
password Text Maybe
UniqueUser name
Model.hs:
import Yesod.Auth.HashDB (HashDBUser, userPasswordHash, setPasswordHash)
import Database.Persist.Quasi (lowerCaseSettings)
...
share [mkPersist sqlSettings, mkMigrate "migrateAll"]
$(persistFileWith lowerCaseSettings "config/models")
instance HashDBUser User where
userPasswordHash = userPassword
setPasswordHash h u = u { userPassword = Just h }
Foundations.hs:
...
import Yesod.Auth
import Yesod.Auth.HashDB (authHashDBWithForm, getAuthIdHashDB, authHashDB)
import Yesod.Auth.Message (AuthMessage (InvalidLogin))
...
instance YesodAuth App where
type AuthId App = UserId
loginDest _ = HomeR
logoutDest _ = HomeR
redirectToReferer _ = True
authPlugins _ = [ authHashDB (Just . UniqueUser) ]
getAuthId creds = getAuthIdHashDB AuthR (Just . UniqueUser) creds
authHttpManager = getHttpManager
Any help would be appreciated. I still kind of suck at Haskell, so this is also my attempt at a crash course in it as well.
This typically means that you don't have an AuthEntity associated type declared, which in turn means that you don't have a YesodAuthPersist instance. In your case, this is probably just:
instance YesodAuthPersist App where
type AuthEntity App = User
This is provided by the Yesod scaffolding.
<?php
$link = mysqli_connect('localhost','root','root');
$link->query('CREATE DATABASE IF NOT EXISTS users');
$link->Select_db('users');
$sql='SELECT id FROM users WHERE email = '.$useremail.' AND username = '.$username;
$results = $link->query($sql);
$numrows = $results->num_rows;
if ($numrows == 1) {
#update user information
} else {
#failed to update
}
?>
It only works part of the time, and i'm not able to nail down an error from it one way or the other. I can confirm that the error pops up on the $numrows=$results->num_rows; line, but as for why, i'm lost. Occasionally it will work as intended, so any and all advice on what i can do to fix it, or at least helping me understand it better is greatly appreciated. Thanks!
Use Double Quotation for query and varchar/string pass with single quotation
$sql="SELECT id FROM users WHERE email = '".$useremail."' AND username = '".$username."'";
$results = $link->query($sql);
$numrows = $results->num_rows();
The reason that your call to num_rows generated an error is that your query had an error, and query() returned false instead of a valid result resource. Because it's a fatal error to try to call a method on a false value, you should always check the return value of query() before using it. Example:
if (!($result = $link->query($sql))) {
die($link->error);
}
Problems with your query:
You create a database named users and make that the default database, then you run a SELECT query from a table named users. There would be no tables in a database you have just created. In SQL, we use SELECT against tables, not databases (these are two different things, analogous to files contained in a directory on a filesystem).
You don't quote the string arguments in your SQL statement. For example, this SQL would be an error:
SELECT id FROM users WHERE email = bill#example.com AND username = bill
It should be this instead:
SELECT id FROM users WHERE email = 'bill#example.com' AND username = 'bill'
I know the quotes get confusing, because you have PHP string quotes and then SQL string quotes, but here are several ways of accomplishing it:
$sql='SELECT id FROM users WHERE email = \''.$useremail.'\' AND username = \''.$username.'\'';
$sql="SELECT id FROM users WHERE email = '".$useremail."' AND username = '".$username."'";
$sql="SELECT id FROM users WHERE email = '{$useremail}' AND username = '{$username}'";
I'm not sure if you have protected your PHP variables appropriately. You must never interpolate PHP variables into SQL strings unless you have escaped the content of the variables.
$useremail_esc = $link->real_escape_string($useremail);
$username_esc = $link->real_escape_string($username);
$sql="SELECT id FROM users WHERE email = '{$useremail_esc}' AND username = '{$username_esc}'";
But it would be better to use prepared statements with parameter placeholders. This is easier to use than escaping variables, and it's more reliable. Here's an example:
$sql="SELECT id FROM users WHERE email = ? AND username = ?";
$stmt = $link->prepare($sql);
$stmt->bind_param("ss", $useremail, $username);
$stmt->execute();
$result = $stmt->get_result();
Notice that you don't use escaping when you use parameters, and you don't put SQL quotes around the ? placeholders.