-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FIX: SQL error "unknown column p.fk_soc" #23941
FIX: SQL error "unknown column p.fk_soc" #23941
Conversation
@@ -248,7 +248,7 @@ public function getAllByProduct($year, $limit = 10) | |||
global $user; | |||
|
|||
$sql = "SELECT product.ref, COUNT(product.ref) as nb, SUM(tl.".$this->field_line.") as total, AVG(tl.".$this->field_line.") as avg"; | |||
$sql .= " FROM ".$this->from.", ".$this->from_line.", ".MAIN_DB_PREFIX."product as product"; | |||
$sql .= " FROM (".$this->from.", ".$this->from_line.", ".MAIN_DB_PREFIX."product as product)"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The syntax using the ( ) does not works on all database version.
The good solution is to have all INNER or OUTER JOIN always just after the table linked so
$sql .= " FROM ".$this->from;
if (empty($user->rights->societe->client->voir) && !$user->socid) {
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
}
$sql .=", ".$this->from_line.", ".MAIN_DB_PREFIX."product as product";
In your example:
SELECT * from A left join C on C.xyz = A.xyz, B ...
is real standard SQL that will work for all databases and versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replaced my earlier version using parentheses with a new proposal using only explicit inner joins: would this be ok? I think it makes the query more consistent by using only one style of join.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, using inner join is also possible.
$sql .= " FROM ".$this->from.", ".$this->from_line.", ".MAIN_DB_PREFIX."product as product"; | ||
if (empty($user->rights->societe->client->voir) && !$user->socid) { | ||
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON p.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id); | ||
$sql = 'SELECT product.ref, COUNT(product.ref) as nb, SUM(tl.' . $this->field_line . ') as total, AVG(tl.' . $this->field_line . ') as avg'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quotes for php string used to forge SQL must be " because the ' is used for the SQL string inside the PHP string.
Thanks to restore like in previous code, this will solve the phpunit regression reporting trouble in sql forging syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for taking so long: initially I didn't understand your request because the only part of this SQL query that has inner strings is built on line 259 and was already using single quotes inside (SQL) and double quotes outside (PHP), so technically, there was no problem with the SQL string in the end. The reason why I had changed the quotation style in the first place was to comply with the .editorconfig rules for Dolibarr (using autoformat).
But now I think I understand that Travis has a more complex (and stringent) ruleset for Dolibarr, so we can't reliably use autoformat (even with the right .editorconfig) when sql strings are involved… or am I mistaken?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use autoformat with no trouble. But if your autoformat include a feature to transform ' into ", you must disable it because we must use " for PHP string when forging a SQL request so we can use the ' for SQL string. I don't have such autoformat feature on eclipse so i do not expereince troubles.
…L string building
This reverts commit 80f4835.
FIX error on home page
To reproduce the bug:
societe->client->voir
from your userdocuments/user/temp/*
)Result:
Latest database access request error: SELECT product.ref, COUNT(product.ref) as nb, SUM(tl.total_ht) as total, AVG(tl.total_ht) as avg FROM llx_propal as p, llx_propaldet as tl, llx_product as product INNER JOIN llx_societe_commerciaux as sc ON p.fk_soc = sc.fk_soc AND sc.fk_user = 1 WHERE p.entity IN (1) AND p.rowid = tl.fk_propal AND tl.fk_product = product.rowid AND p.datep BETWEEN '2023-01-01 00:00:00' AND '2023-12-31 23:59:59' GROUP BY product.ref ORDER BY nb DESC
Return code for latest database access request error: DB_ERROR_NOSUCHFIELD
Information for latest database access request error: Unknown column 'p.fk_soc' in 'on clause'
Analysis
After researching it a bit, I found this stackoverflow topic which explains the problem: ANSI-92 joins (i.e. joins using the LEFT JOIN, INNER JOIN etc. keywords) take precedence over ANSI-89 joins (i.e. joins by comma in table list) and therefore the join on
llx_societe_commerciaux
occurs before the join onllx_propal
but itsON
clause requiresllx_propal
to be joined first.Basically,
is not the same as
The responder also recommended not to mix the two styles of joins in one request, but I found it easier to not rewrite the whole query (but we could keep this in mind for the future).