CakePHP count() return wrong results? - cakephp

CakePHP 3.6.14
This code reproduce wrong number:
$where = [
'Postings.source' => $source,
'Postings.approved' => 1,
'Postings.deleted' => 0,
'Postings.disabled' => 0
];
if ($source !== null) {
$where['Postings.created >='] = '(NOW() - INTERVAL 3 DAY)';
}
$count = $this->Postings
->find()
->where($where)
->count();
debug($count); exit;
// 77568 total of all records
########## DEBUG ##########
[
'Postings.source' => 'xzy',
'Postings.approved' => (int) 1,
'Postings.deleted' => (int) 0,
'Postings.disabled' => (int) 0,
'Postings.created >=' => '(NOW() - INTERVAL 3 DAY)'
]
//SQL produced by this query:
SELECT (COUNT(*)) AS `count`
FROM postings Postings
WHERE (
Postings.source = 'xzy'
AND Postings.approved = 1
AND Postings.deleted = 0
AND Postings.disabled = 0
AND Postings.created >= '(NOW() - INTERVAL 3 DAY)' // <<<< with quotes
)
but raw sql query:
SELECT COUNT(*) as `count
FROM `postings`
WHERE `source` = 'xzy'
AND `approved` = 1
AND `deleted` = 0
AND `disabled` = 0
AND `created` >= (NOW() - INTERVAL 3 DAY) // <<< without quotes
// return correct num 2119
How to fix?

Values on the right hand side of a key => value condition are always subject to binding/casting/escaping, unless it's an expression object. Look at the generated query, your SQL snippet will end up as a string literal, ie:
created >= '(NOW() - INTERVAL 3 DAY)'
Long story short, use an expression, either a raw one:
$where['Postings.created >='] = $this->Postings->query()->newExpr('NOW() - INTERVAL 3 DAY');
or use the functions builder:
$builder = $this->Postings->query()->func();
$where['Postings.created >='] = $builder->dateAdd($builder->now(), -3, 'DAY');
See also
Cookbook > Database Access & ORM > Query Builder > Advanced Conditions
Cookbook > Database Access & ORM > Query Builder > Using SQL Functions

You should use Query builder and add to select method count function.
Everything is described here: https://book.cakephp.org/3.0/en/orm/query-builder.html#using-sql-functions

Related

Please tell me how to fill in the fields in the list that lies on the map

I have a map
Map<Id, List<ExpenseController.MonthRow>> monthsPerKeeper = new Map<Id, List<ExpenseController.MonthRow>>();
This is how she looks:
Right now I'm only showing the months ("monthNumber") that are full.
I need to fill in all the missing ("monthNumber") and the ("amount") field for that ("monthNumber") should be 0.
It should look like this:
I tried to get the value from the map by id (that is, the List)
but I don't know how to refer to the fields in this List to fill them in
for (Id c : monthsPerKeeper.keySet()) {
if(monthsPerKeeper.containsKey(c)) {
for (ExpenseController.MonthRow a : monthsPerKeeper.get(c)) {
List<ExpenseController.MonthRow> monthsListAdd = new List<ExpenseController.MonthRow>();
for (Integer i = 1; i < 13; i++) {
if (!monthsPerKeeper.get(c).monthNumber.containsKey(i)) {
ExpenseController.MonthRow row = new ExpenseController.MonthRow();
row.monthName = ExpenseController.monthNumbers.get(i);
row.amount = 0;
row.monthNumber = i;
monthsListAdd.add(row);
}
}
}
}
}
so you have monthsListAdd with say 5 dummy months and want to add it to the original list of 7 real months? Many ways to do it, seeing how your screenshot list is unsorted and really the gaps (no expenses this month) can be anywhere... I'd probably reverse the whole thing, start with 12 placeholders with 0 amounts and just update them as I go through list...
Anyway:
After that for (ExpenseController.MonthRow a : monthsPerKeeper.get(c)) { ends add this:
monthsPerKeeper.get(c).addAll(monthsListAdd);
I stil think you'll have this in rubbish order so maybe read up about "implements Comparable" to sort your list of helper objects after they're all added up?
edit
To make it cleaner I'd use a Map where key is month number and value is... well, if all you need is Amount then probably Map<Integer,Decimal> would do. If you'd want to display more - Map<Integer, ExpenseController.MonthRow> probably. Or you know, use the fact that List could have month numbers as indexes ;)
Consider this query (works in my sandbox and returns me something but with gaps. And that's OK)
SELECT CALENDAR_MONTH(CloseDate), SUM(Amount)
FROM Opportunity
WHERE CloseDate = THIS_YEAR AND IsWon = true AND Owner.Profile.Name = 'System Administrator' AND Amount != null
GROUP BY CALENDAR_MONTH(CloseDate)
It's not even sorted - but I don't care.
Map<Integer, Decimal> myMap = new Map<Integer, Decimal>{
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
10 => 0,
11 => 0,
12 => 0
};
for(AggregateResult ar : [SELECT CALENDAR_MONTH(CloseDate) m, SUM(Amount) a
FROM Opportunity
WHERE CloseDate = THIS_YEAR AND IsWon = true AND Owner.Profile.Name = 'System Administrator' AND Amount != null
GROUP BY CALENDAR_MONTH(CloseDate)]){
myMap.put((Integer) ar.get('m'), (Decimal) ar.get('a'));
}
for(Integer i = 1; i < 13; ++i){
System.debug(i + ' ' + DateTime.newInstance(2022,i,1).format('MMMM') + ': ' + myMap.get(i));
// instead of debug you'd have your someList.add(new ExpenseController.MonthRow(...) or whatever
}

Bad SQL query Disk full (/tmp/#sql_58f_0); waiting for someone to free some space

I have Presta, and I like it but..
Now I get this strange error:
Bad SQL query Disk full (/tmp/#sql_58f_0); waiting for someone to free
some space...
I googled a lot, but did not find any solution.
After I added EAN codes in my products field, my shop shows:
No featured products at this time.
Prior to this all seemed to look fine.
I restored an old backup (from 2 months ago) and noticed that it already did had the same SQL error and after I added one EAN code, I see the same no featured products.
Not sure if the restore placed the shop back in 100 old condition, but with ean code's I have a total non working shop.
Even removing them dos not solve my problem.
I turned on debugging and received this as result:
{PrestaShopDatabaseException]
Disk full (/tmp/#sql_58f_0); waiting for someone to free some space...
SELECT
a.`id_category`, `name`, `description`, sa.`position` AS `position`, `active`
, sa.position position
FROM `ps_category` a
LEFT JOIN `ps_category_lang` b ON (b.`id_category` = a.`id_category` AND b.`id_lang` = 1 AND b.`id_shop` = 1)
LEFT JOIN `ps_category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = 1)
WHERE 1 AND `id_parent` = 2
ORDER BY sa.`position` ASC LIMIT 0, 50
at line 791 in file classes/db/Db.php:
786. if ($webservice_call && $errno) {
787. $dbg = debug_backtrace();
788. WebserviceRequest::getInstance()->setError(500, '[SQL Error] '.$this->getMsgError().'. From '.(isset($dbg[3]['class']) ? $dbg[3]['class'] : '').'->'.$dbg[3]['function'].'() Query was : '.$sql, 97);
789. } elseif (_PS_DEBUG_SQL_ && $errno && !defined('PS_INSTALLATION_IN_PROGRESS')) {
790. if ($sql) {
**791. throw new PrestaShopDatabaseException($this->getMsgError().'<br /><br /><pre>'.$sql.'</pre>');**
792. }
793.
794. throw new PrestaShopDatabaseException($this->getMsgError());
795. }
796. }
DbCore->displayError - [line 425 - classes/db/Db.php] - [1 Arguments]
420. $this->result = $this->_query($sql);
421. }
422. }
423.
424. if (_PS_DEBUG_SQL_) {
**425. $this->displayError($sql);**
426. }
427.
428. return $this->result;
429. }
430.
DbCore->query - [line 643 - classes/db/Db.php] - [1 Arguments]
Argument [0]
SELECT
a.`id_category`, `name`, `description`, sa.`position` AS `position`, `active`
, sa.position position
FROM `ps_category` a
LEFT JOIN `ps_category_lang` b ON (b.`id_category` = a.`id_category` AND b.`id_lang` = 1 AND b.`id_shop` = 1)
LEFT JOIN `ps_category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = 1)
WHERE 1 AND `id_parent` = 2
ORDER BY sa.`position` ASC LIMIT 0, 50
DbCore->executeS - [line 3212 - classes/controller/AdminController.php] - [3 Arguments]
3207. '.($this->_tmpTableFilter ? ' * FROM (SELECT ' : '').$this->_listsql.$sql_from.$sql_join.' WHERE 1 '.$sql_where.
3208. $sql_order_by.$sql_limit;
3209. $list_count = 'SELECT COUNT(*) AS `'._DB_PREFIX_.$this->table.'` '.$sql_from.$sql_join.' WHERE 1 '.$sql_where;
3210. }
3211.
**3212. $this->_list = Db::getInstance()->executeS($this->_listsql, true, false);**
3213.
3214. if ($this->_list === false) {
3215. $this->_list_error = Db::getInstance()->getMsgError();
3216. break;
3217. }
AdminControllerCore->getList - [line 253 - controllers/admin/AdminCategoriesController.php] - [6 Arguments]
248. return parent::renderList();
249. }
250.
251. public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false)
252. {
**253. parent::getList($id_lang, $order_by, $order_way, $start, $limit, Context::getContext()->shop->id);**
254. // Check each row to see if there are combinations and get the correct action in consequence
255.
256. $nb_items = count($this->_list);
257. for ($i = 0; $i < $nb_items; $i++) {
258. $item = &$this->_list[$i];
AdminCategoriesControllerCore->getList - [line 2333 - classes/controller/AdminController.php] - [1 Arguments]
Argument [0]
1
AdminControllerCore->renderList - [line 248 - controllers/admin/AdminCategoriesController.php]
243. $this->tpl_list_vars['delete_category'] = true;
244. $this->tpl_list_vars['REQUEST_URI'] = $_SERVER['REQUEST_URI'];
245. $this->tpl_list_vars['POST'] = $_POST;
246. }
247.
**248. return parent::renderList();**
249. }
250.
251. public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false)
252. {
253. parent::getList($id_lang, $order_by, $order_way, $start, $limit, Context::getContext()->shop->id);
AdminCategoriesControllerCore->renderList - [line 2034 - classes/controller/AdminController.php]
2029. } elseif ($this->display == 'details') {
2030. $this->content .= $this->renderDetails();
2031. } elseif (!$this->ajax) {
2032. $this->content .= $this->renderModulesList();
2033. $this->content .= $this->renderKpis();
**2034. $this->content .= $this->renderList();**
2035. $this->content .= $this->renderOptions();
2036.
2037. // if we have to display the required fields form
2038. if ($this->required_database) {
2039. $this->content .= $this->displayRequiredFields();
AdminControllerCore->initContent - [line 199 - controllers/admin/AdminCategoriesController.php]
194. 'url_delete' => htmlentities($_SERVER['REQUEST_URI']),
195. 'boxes' => $this->boxes,
196. ));
197. }
198.
**199. parent::initContent();**
200. }
201.
202. public function setMedia()
203. {
204. parent::setMedia();
AdminCategoriesControllerCore->initContent - [line 189 - classes/controller/Controller.php]
184. if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className))) {
185. $this->initHeader();
186. }
187.
188. if ($this->viewAccess()) {
**189. $this->initContent();**
190. } else {
191. $this->errors[] = Tools::displayError('Access denied.');
192. }
193.
194. if (!$this->content_only && ($this->display_footer || (isset($this->className) && $this->className))) {
ControllerCore->run - [line 367 - classes/Dispatcher.php]
362. if (isset($params_hook_action_dispatcher)) {
363. Hook::exec('actionDispatcher', $params_hook_action_dispatcher);
364. }
365.
366. // Running controller
**367. $controller->run();**
368. } catch (PrestaShopException $e) {
369. $e->displayMessage();
370. }
371. }
372.
DispatcherCore->dispatch - [line 58 - admin/index.php]
53. if (!isset($_REQUEST['controller']) && isset($_REQUEST['tab'])) {
54. $_REQUEST['controller'] = strtolower($_REQUEST['tab']);
55. }
56.
57. // Prepare and trigger admin dispatcher
**58. Dispatcher::getInstance()->dispatch();**
Google isn't much help.
Have you seen this before, and how can I (or someone else) fix this?
Thank you for feedback!
p.s. the domain is Giantjeans.com
It seems that in your web hosting the disk space (in this case the database size) is less or the SQL-server is having too many requests to the database at the same time.
Because of which Prestashop is not able to write the data. In order to fix the issues, you need to check the server error to know the exact reason.
It is recommended that you upgrade your server and get some more free space.

`+' nil can't be coerced into FixNum (TypeError) won't go away [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm using HTTParty to connect to stockfighter.io 's API and getting a quote of a stock, which I then extract a price per share from and append it to the end of the $averageArr array.
I'm trying to average the last five values of a constantly updating array, $averageArr, and so I thought I would make a variable sum set it to zero, add those last five values to it and then divide it by 5 to get a dynamic and changing average.
Here's my code:
require 'rubygems'
require 'httparty'
require 'json'
apikey = 'API_KEY_FOR_LOGIN_HERE'
venue = "VENUEX"
stock = "FOOBAR"
base_url = "https://api.stockfighter.io/ob/api"
account = "MY_ACCOUNT_HERE"
$averageArr = []
$counter = 0
$currAve = 0
def getQuote(stock, venue, account)
response = HTTParty.get("https://api.stockfighter.io/ob/api/venues/#{venue}/stocks/#{stock}/quote")
orderbook = response.parsed_response
puts orderbook["ok"]
return orderbook["last"]
puts orderbook["lastTrade"]
end
def getAverage(stock, venue, account)
$averageArr.push(getQuote(stock, venue, account))
$counter += 1
if $counter > 5
sum = 0
#line 43
for i in 1..5 do
# this one is line 45
sum += $averageArr[$averageArr.count - i]
end
return sum/5
$currAve = sum/5
else
return 'WAITING FOR QUOTE. CURRENT:'
end
end
# line 62
for i in 1..10 do
# line 64
getAverage(stock, venue, account)
if $counter > 5
if getQuote(stock, venue, account) < $currAve - 25 and numShares < 999
order = {
"account" => account,
"venue" => venue,
"symbol" => stock,
"price" => 1, #$250.00 -- probably ludicrously high
"qty" => 1,
"direction" => "buy",
"orderType" => "market" # See the order docs for what a limit order is
}
response = HTTParty.post("#{base_url}/venues/#{venue}/stocks/#{stock}/orders",
:body => JSON.dump(order),
:headers => {"X-Starfighter-Authorization" => apikey}
)
elsif getQuote(stock, venue, account) > $currAve + 25 and numShares > 0
order = {
"account" => account,
"venue" => venue,
"symbol" => stock,
"price" => 1, #$250.00 -- probably ludicrously high
"qty" => 1,
"direction" => "sell",
"orderType" => "market" # See the order docs for what a limit order is
}
response = HTTParty.post("#{base_url}/venues/#{venue}/stocks/#{stock}/orders",
:body => JSON.dump(order),
:headers => {"X-Starfighter-Authorization" => apikey}
)
end
end
end
I've been having difficulty with line 45 (commented), in which I get errors about FixNum and nil:
/Users/kaichristensen/Dropbox/Kai/Stockfighter/level_three_selling.rb:45:in `+': nil can't be coerced into Fixnum (TypeError)
from /Users/kaichristensen/Dropbox/Kai/Stockfighter/level_three_selling.rb:45:in `block in getAverage'
from /Users/kaichristensen/Dropbox/Kai/Stockfighter/level_three_selling.rb:43:in `each'
from /Users/kaichristensen/Dropbox/Kai/Stockfighter/level_three_selling.rb:43:in `getAverage'
from /Users/kaichristensen/Dropbox/Kai/Stockfighter/level_three_selling.rb:64:in `block in <main>'
from /Users/kaichristensen/Dropbox/Kai/Stockfighter/level_three_selling.rb:62:in `each'
from /Users/kaichristensen/Dropbox/Kai/Stockfighter/level_three_selling.rb:62:in `<main>'
I might be trying to access and index out of scope on the array, but that doesn't seem to be the problem. Any help would be appreciated.
Your syntax is fine. The problem is that your methods are not validating data.
a += b expands to a = a + b, which will throw the error you're facing when b is nil.
You need to make sure that getQuote always returns a number, or cast whatever you want to average into a number before performing mathematical operations.
For the former, you can change return orderbook["last"] to return orderbook["last"].to_f
For the latter, sum += $averageArr[$averageArr.count - i].to_f

Evaluating equality in perl using elements taken from an array ref

I have a small perl script that needs to evaluate the equality of two parameters and a small return from the database.
my ($firstId, $secondId, $firstReturnedId, $secondReturnedId, $picCount);
my $pics = $dbh->prepare(qq[select id from pictures limit 10]);
$firstId = q->param('firstId');
$secondId = q->param('secondId');
$pics->execute or die;
my $picids = $pics->fetchall_arrayref;
$picCount = scalar(#{$picids});
$firstReturnedId = $picCount > 0 ? shift(#{$picids}) : 0;
$secondReturnedId = $picCount > 1 ? pop(#{$picids}) : $firstReturnedId;
Here, a quick look at my debugger shows that $picCount = 1 and $firstReturnedId = 9020 and $secondReturnedId = 9020. However, they are both denoted as
ARRAY(0x9e79184)
0 9020
in the debugger so when I perform the final check
my $result = (($firstId == $firstReturnedId) && ($secondId == $secondReturnedId)) ? 1 : 0;
I get $result = 0, which is not what I want.
What am I doing wrong?
DBI::fetchall_arrayref returns a reference to a list of "row results". But since there could be more than one value in a row result (e.g., your query could have been select id,other_field from pictures), each row result is also a reference to a list. This means you have one more dereferencing to do in order to get the result you want. Try:
$picCount = scalar(#{$picids});
if ($picCount > 0) {
my $result = shift #{$picids};
$firstReturnedId = $result->[0];
} else {
$firstReturnedId = 0;
}
if ($picCount > 1) {
my $result = pop #{$picids};
$secondReturnedId = $result->[0];
} else {
$secondReturnedId = $firstReturnedId;
}
or if you still want to use a concise style:
$firstReturnedId = $picCount > 0 ? shift(#{$picids})->[0] : 0;
$secondReturnedId = $picCount > 1 ? pop(#{$picids})->[0] : $firstReturnedId;

Is it better to change the db schema?

I'm building a web app with django. I use postgresql for the db. The app code is getting really messy(my begginer skills being a big factor) and slow, even when I run the app locally.
This is an excerpt of my models.py file:
REPEATS_CHOICES = (
(NEVER, 'Never'),
(DAILY, 'Daily'),
(WEEKLY, 'Weekly'),
(MONTHLY, 'Monthly'),
...some more...
)
class Transaction(models.Model):
name = models.CharField(max_length=30)
type = models.IntegerField(max_length=1, choices=TYPE_CHOICES) # 0 = 'Income' , 1 = 'Expense'
amount = models.DecimalField(max_digits=12, decimal_places=2)
date = models.DateField(default=date.today)
frequency = models.IntegerField(max_length=2, choices=REPEATS_CHOICES)
ends = models.DateField(blank=True, null=True)
active = models.BooleanField(default=True)
category = models.ForeignKey(Category, related_name='transactions', blank=True, null=True)
account = models.ForeignKey(Account, related_name='transactions')
The problem is with date, frequency and ends. With this info I can know all the dates in which transactions occurs and use it to fill a cashflow table. Doing things this way involves creating a lot of structures(dictionaries, lists and tuples) and iterating them a lot. Maybe there is a very simple way of solving this with the actual schema, but I couldn't realize how.
I think that the app would be easier to code if, at the creation of a transaction, I could save all the dates in the db. I don't know if it's possible or if it's a good idea.
I'm reading a book about google app engine and the datastore's multivalued properties. What do you think about this for solving my problem?.
Edit: I didn't know about the PickleField. I'm now reading about it, maybe I could use it to store all the transaction's datetime objects.
Edit2: This is an excerpt of my cashflow2 view(sorry for the horrible code):
def cashflow2(request, account_name="Initial"):
if account_name == "Initial":
uri = "/cashflow/new_account"
return HttpResponseRedirect(uri)
month_info = {}
cat_info = {}
m_y_list = [] # [(month,year),]
trans = []
min, max = [] , []
account = Account.objects.get(name=account_name, user=request.user)
categories = account.categories.all()
for year in range(2006,2017):
for month in range(1,13):
month_info[(month, year)] = [0, 0, 0]
for cat in categories:
cat_info[(cat, month, year)] = 0
previous_months = 1 # previous months from actual
next_months = 5
dates_list = month_year_list(previous_month, next_months) # Returns [(month,year)] from the requested range
m_y_list = [(date.month, date.year) for date in month_year_list(1,5)]
min, max = dates_list[0], dates_list[-1]
INCOME = 0
EXPENSE = 1
ONHAND = 2
transacs_in_dates = []
txs = account.transactions.order_by('date')
for tx in txs:
monthyear = ()
monthyear = (tx.date.month, tx.date.year)
if tx.frequency == 0:
if tx.type == 0:
month_info[monthyear][INCOME] += tx.amount
if tx.category:
cat_info[(tx.category, monthyear[0], monthyear[1])] += tx.amount
else:
month_info[monthyear][EXPENSE] += tx.amount
if tx.category:
cat_info[(tx.category, monthyear[0], monthyear[1])] += tx.amount
if monthyear in lista_m_a:
if tx not in transacs_in_dates:
transacs_in_dates.append(tx)
elif tx.frequency == 4: # frequency = 'Monthly'
months_dif = relativedelta.relativedelta(tx.ends, tx.date).months
if tx.ends.day < tx.date.day:
months_dif += 1
years_dif = relativedelta.relativedelta(tx.ends, tx.date).years
dif = months_dif + (years_dif*12)
dates_range = dif + 1
for i in range(dates_range):
dt = tx.date+relativedelta.relativedelta(months=+i)
if (dt.month, dt.year) in m_y_list:
if tx not in transacs_in_dates:
transacs_in_dates.append(tx)
if tx.type == 0:
month_info[(fch.month,fch.year)][INCOME] += tx.amount
if tx.category:
cat_info[(tx.category, fch.month, fch.year)] += tx.amount
else:
month_info[(fch.month,fch.year)][EXPENSE] += tx.amount
if tx.category:
cat_info[(tx.category, fch.month, fch.year)] += tx.amount
import operator
thelist = []
thelist = sorted((my + tuple(v) for my, v in month_info.iteritems()),
key = operator.itemgetter(1, 0))
thelistlist = []
for atuple in thelist:
thelistlist.append(list(atuple))
for i in range(len(thelistlist)):
if i != 0:
thelistlist[i][4] = thelistlist[i-1][2] - thelistlist[i-1][3] + thelistlist[i-1][4]
list = []
for el in thelistlist:
if (el[0],el[1]) in lista_m_a:
list.append(el)
transactions = account.transactions.all()
cats_in_dates_income = []
cats_in_dates_expense = []
for t in transacs_in_dates:
if t.category and t.type == 0:
if t.category not in cats_in_dates_income:
cats_in_dates_income.append(t.category)
elif t.category and t.type == 1:
if t.category not in cats_in_dates_expense:
cats_in_dates_expense.append(t.category)
cat_infos = []
for k, v in cat_info.items():
cat_infos.append((k[0], k[1], k[2], v))
Depends on how relevant App Engine is here. P.S. If you'd like to store pickled objects as well as JSON objects in the Google Datastore, check out these two code snippets:
http://kovshenin.com/archives/app-engine-json-objects-google-datastore/
http://kovshenin.com/archives/app-engine-python-objects-in-the-google-datastore/
Also note that the Google Datastore is a non-relational database, so you might have other trouble refactoring your code to switch to that.
Cheers and good luck!

Resources