Perl and SQLite - request to improve/optimize the multiple SQL INSERT queries - sql

I have quite a lot of data in JSON files that I need to convert to the SQLite database. I did a simple loop with the INSERT query, but the queries take a lot of time. I am a hobbyist and I am learning all the time. I think that there must be a more professional solution.
use JSON::XS;
use DBI;
my $CCC = 'string';
# start connection to SQLite
my $dbh = DBI->connect(
"dbi:SQLite:dbname=aaaa.db", "", "", { RaiseError => 1 }, ) or die $DBI::errstr;
my $stmt = "CREATE TABLE IF NOT EXISTS $CCC (id INTEGER PRIMARY KEY AUTOINCREMENT, start INTEGER UNIQUE, open REAL NOT NULL, high REAL NOT NULL, low REAL NOT NULL, close REAL NOT NULL, vwp REAL NOT NULL, volume REAL NOT NULL, trades INTEGER NOT NULL)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
# Open file.json
open(my $fh, '<', file.json) or die "cannot open file";
{
local $/;
$data = <$fh>;
}
# Converting JSON format to Perl's variables
my $coder = JSON::XS->new->ascii->pretty->allow_nonref;
my $json = $coder->decode ($data);
# Loop. Im inserting every hash ({}) from file.json by INSERT sql statement
foreach (#{$json}) {
my $stmt = "INSERT OR IGNORE INTO $CCC values (null, strftime('%s',\'$_->{T}\'), $_->{O}, $_->{H}, $_->{L}, $_->{C}, ".(($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4).", $_->{V}, 1)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
}
file.json
[{"O": 1.0, "H": 1.0, "L": 0.00014, "C": 0.000145, "V": 176703.92394752, "T": "2018-02-16T00:00:00", "BV": 25.71390226}, {"O": 0.00014499, "H": 0.00014499, "L": 0.00011101, "C": 0.00012599, "V": 247646.2068748, "T": "2018-02-16T00:05:00", "BV": 30.66246148}, {"O": 0.00012599, "H": 0.0001295, "L": 0.000122, "C": 0.00012699, "V": 102563.86201627, "T": "2018-02-16T00:10:00", "BV": 12.88322597}]
Do you know any more efficient way?

I think you should have the statement and prepare outside the foreach loop (using placeholders), then execute inside the loop. The prepare normally only needs to be done once.
foreach (#{$json}) {
my $stmt = "INSERT OR IGNORE INTO $CCC values (null, strftime('%s',\'$_->{T}\'), $_->{O}, $_->{H}, $_->{L}, $_->{C}, ".(($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4).", $_->{V}, 1)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
}
Perhaps this:
my $stmt = "INSERT INTO $CCC values (?, ?, ?, ?, ?, ?, ?, ?, ?)";
my $sth = $dbh->prepare( $stmt );
foreach (#{$json}) {
$sth->execute(undef, $_->{T}, $_->{O}, $_->{H}, $_->{L}, $_->{C}, ($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4, $_->{V}, 1) or die $DBI::errstr;
}
Update: placed undef as first parameter as suggested by Kjetil S.

Related

Powershell Json object from object

I have a method that returns a Json object from a query using the FOR JOSN PATH approach.
Example:
SELECT State, COUNT(*) AS Items
FROM dbo.States
WHERE SomeFilterColumn = #FilterParam
GROUP BY State
FOR JSON PATH
This returns
[
{
"State": "Pending",
"Items": 23
},
{
"State": "Finished",
"Items", 7736
}
]
I also have a function in Powershell that returns the result. However I have issues how it is returned.
function Get-Json-From-Query {
param(
[Int32]$filterParam
)
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
...
$SqlCmd = $SqlConnection.CreateCommand();
$SqlCmd.CommandText = $Query #The query shown above
$SqlCmd.Parameters.Add("#FilterParam", $filterParam);
$SqlCmd.ExecuteScalar()
}
However I do not know how to get the result of my query properly added to a JSON value.
I tried many things like:
#{
States = (Get-Json-From-Query -filterParam 1234)
}
However this gives me also the param information which I do not want:
Expecting
{ "States": [... The Array show above ... ] }
Actual
{
"States": [
{
"CompareInfo": 0,
"XmlSchemaCollectionDatabase": "",
"XmlSchemaCollectionOwningSchema": "",
"XmlSchemaCollectionName": "",
"ForceColumnEncryption": false,
"DbType": 11,
"LocaleId": 0,
"ParameterName": "#FilterParam",
"Precision": 0,
"Scale": 0,
"SqlDbType": 8,
"SqlValue": "1234",
"UdtTypeName": "",
"TypeName": "",
"Value": 1234,
"Direction": 1,
"IsNullable": false,
"Offset": 0,
"Size": 0,
"SourceColumn": "",
"SourceColumnNullMapping": false,
"SourceVersion": 512
},
"[{\"State\":\"Pending\",\"Items\":23},{\"State\":\"Finished\",\"Items\":7763}]"
]
}
How do I get the right data in my Json object?

Error Exception Array to string conversion

I want to have a response in postman for my API... but when I send a raw in body of postman
I faced to array to string conversion error
Error Exception (E_NOTICE)
Array to string conversion
this is my raw
{
"account_type": "real",
"address": "12131",
"card_bank": "",
"city": {
"id": 436,
"name": "مشهد",
"state_id": 11,
"state_name": "خراسان رضوی"
},
"code_melli": "",
"email": "",
"family": "اسداله پور",
"id": 171,
"mobile": "0911111111",
"name": "مهدی",
"phone": "",
"role": "usual",
"card": [
{
"count": 1,
"id": 2,
"id_product": 267,
"productM": null,
"seller": null,
"id_seller": 0,
"totalPrice": "97500"
},
{
"count": 1,
"id": 3,
"id_product": 696,
"productM": null,
"seller": null,
"id_seller": 0,
"totalPrice": "115000"
}
],
"state": {
"id": 11,
"name": "خراسان رضوی"
}
}
and this is my web service
about this route
public function ChangeInformation(Request $request)
{
$validator = Validator::make(
$request->all(),
[
'name' => 'required',
'family' => 'required',
'mobile' => 'required',
],
[
'name.required' => 'لطفا نام خود را وارد کنید',
'family.required' => 'لطفا نام خانوادگی خود را وارد کنید',
'mobile.required' => 'لطفا موبایل خود را وارد کنید',
]);
if ($validator->fails()) {
self::$result_json['error'] = 1;
self::$result_json['error_code'] = 1;
self::$result_json['msg'] = $validator->messages()->first();
}
else{
$user = DB::table('user_app')
->where('id', $request->get('token'))
->first();
$input = $request->except('img');
/*if ($request->hasFile('img')) {
$file_param = $request->file('img');
$fileName = $file_param->getClientOriginalName();
$fileName = substr($fileName, 0, strrpos($fileName, '.'));
$fileName = str_replace(' ', '', $fileName);
$Random_Number = rand(0, 9999);
$name_file_new = $fileName . '-' . $Random_Number . '.' . $file_param->getClientOriginalExtension();
//$thumb_img = Image::make($file->getRealPath())->resize(100, 100);
$destinationPath = 'uploads/avatars/';
$file_param->move($destinationPath, $name_file_new);
$path_file = 'uploads/avatars/' . $name_file_new;
$input['img'] = $path_file;
}
else {
self::$result_json['error'] = 1;
self::$result_json['error_code'] = 1;
self::$result_json['msg'] = 'تصویر نادرست است .';
}*/
DB::table('user_app')
->where('id',$user->id)
->update($input);
$city = DB::table('cities')
->where('id', $input['shahr'])
->first();
$state = DB::table('state')
->where('id', $input['ostan'])
->first();
$user_data = DB::table('user_app')
->where('id',$user->id)
->select('account_type', 'address','email','card_bank', 'shahr as city',
'family', 'id', 'mobile', 'name', 'img', 'phone', 'role', 'ostan as state', 'zip_code')
->first();
$user_data->city = $city;
$user_data->state = $state;
self::$result_json['success'] = 1;
self::$result_json['user_data'] = $user_data;
}
it worked when I send data in form_data but do not work in raw when i send my data
you need to convert your associative array into json object format using "json_encode() function" which is string, postman cannot read array, I hope this one will do

Asserting and using conditions for an array response in Karate

I've got a request that returns a list of responses in two possible structures, depending on the 'status'.
{
"listSize": 2,
"itemList": [
{
"id": ,
"Name": "",
"submittedOn": "",
"Reference": null,
"status": "Receipted",
"response": null
},
{
"id": 12345,
"submittedOn": "",
"Reference": null,
"status": "Failed",
"response": {
"xml": "",
"formErrors": [
{
"error_type": "",
"error_location":"",
"error_message": "",
}
]
}
},
]
}
I need to check the structure for the status being either 'Receipted' or 'Failed'. In Java I would use a for loop and an if statement within it to check the response field with different criteria depending on the 'status' field. (Example below)
for (int i = 0; i < response.length; i++){
if (response[i].status.equals("receipted")){
//do something
}
else{ //failed
//do something else
}
}
How could I achieve something similar in Karate? Should I use a Java Helper?
First, you are encouraged to write static expected results in tests. That said there are multiple ways to do this, here's one:
* def failedSchema = { xml: '#string', formErrors: '#array' }
* def isValid = function(x){ if (x.status == 'Receipted') return x.response == null; return karate.match(x.response, failedSchema).pass }
* match each response.itemList == '#? isValid(_)'
Here's another example: https://stackoverflow.com/a/62567412/143475
There are other ways to loop in Karate, but not really designed for matching: https://github.com/intuit/karate#loops
Here's an extreme example involving JSON transformation to make it easier to match: https://stackoverflow.com/a/53120851/143475
Also refer: https://github.com/intuit/karate#conditional-logic

How to assert 2 keys in many objects

response =
[
{
id: "1",
modelId: "301",
modelName: "x",
trimId: "301",
trimName: "up!",
derivativeName: "xx",
fuelType: "PETROL",
tco: {
price: {
tco: null,
retail: 12,
offer: null,
subsidy: null,
residual: null
},
milesPerYear: 10000,
mpg: 51.5,
fuelCost: 1.1,
milesPerKW: 0,
monthsOfOwnership: 48,
energyCost: 12,
tax: 42,
comparable: false
}
},
{
id: "1239",
modelId: "301",
modelName: "up!",
trimId: "301",
trimName: "x",
derivativeName: "xx",
fuelType: "PETROL",
tco: {
price: {
tco: null,
retail: 1,
offer: null,
subsidy: null,
residual: null
},
milesPerYear: 10000,
mpg: 53.2,
fuelCost: 1.1,
milesPerKW: 0,
monthsOfOwnership: 48,
energyCost: 12,
tax: 4,
comparable: false
}
}
]
Been trying to work this out but can't figure out the best way to do it.
I'm trying to check when the key fuelType = PETROL then key fuelCost must equal 1.1
There are many objects within the response and I want to assert the 2 keys (fuelType and Fuelcost) in every object.
I tried the following:
Given path 'url'
When method GET
Then match each response[*] contains {[*].fuelType:PETROL , [*].tco.fuelCost:1.1}
Please help
thanks
Try this, adapt if needed:
* def isValid = function(x){ return if x.fuelType == 'PETROL' && x.fuelCost == 1.1 }
* match each response == '#? isValid(_)'

Insert facebook profile picture into blob column mysql

I'm trying to integrate facebook connect into our website (Symfony) for this we use FOSFacebookBundle.
I was able to do that and getting my facebook id, first_name, and last_name and insert them into a new user in our fos_user column.
Regarding the user profile picture I keep receive an exception :
An exception occurred while executing 'INSERT INTO fos_user (username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expired, expires_at, confirmation_token, password_requested_at, roles, credentials_expired, credentials_expire_at, nom, prenom, solde, path, sexe, date_Naissance, facebookId, photo) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params ["1223800560964254", "1223800560964254", "******#gmail.com", "*********#gmail.com", 1, "", "", null, 0, 0, null, null, null, "a:1:{i:0;s:12:\"ROLE_PORTEUR\";}", 0, null, "Mohamed", "Elloumi", null, null, null, null, "1223800560964254", {"data":{"is_silhouette":false,"url":"https:\/\/fbcdn-profile-a.akamaihd.net\/hprofile-ak-ash2\/v\/t1.0-1\/c85.25.315.315\/s50x50\/580232_622196307791352_1230572455_n.jpg?oh=17c02ae42bb18d3ddbe3cfdf04239049&oe=57AC3250&__gda__=1474408706_227fd87692ead8189d332a4898571e62"}}]:
Notice: Array to string conversion
And I think that it's because I'm trying to add the full picture api Graph response into the blob column:
{
"picture": {
"data": {
"is_silhouette": false,
"url": "https://fbcdn-profile-a.akamaihd.net/****"
}
},
"id": "792374454106869"
}
I guess that I only need the insert this line into my blob column :
"url": "https://fbcdn-profile-a.akamaihd.net/****"
I'm using this php function to insert into the fos_user table :
public function setFBData($fbdata) // C'est dans cette méthode que vous ajouterez vos informations
{
if (isset($fbdata['id'])) {
$this->setFacebookId($fbdata['id']);
$this->addRole('ROLE_PORTEUR');
}
if (isset($fbdata['first_name'])) {
$this->setNom($fbdata['first_name']);
}
if (isset($fbdata['last_name'])) {
$this->setPrenom($fbdata['last_name']);
}
if (isset($fbdata['email'])) {
$this->setEmail($fbdata['email']);
}
if (isset($fbdata['picture'])) {
$this->setPhoto($fbdata['picture']);
}
}
why a blob? A varchar(255) should suffice for a url. You should be able to access the url in the picture array like this:
$fbdata['picture']['data']['url']