Двойные кавычки в Postgresql могут считаться вредными из-за , как работают двойные кавычки . Их следует использовать только тогда, когда есть вероятность путаницы с ключевым словом.
"tm.senderId"
не означает senderId
в псевдониме tm
. Поскольку .
цитируется, это означает в точности идентификатор tm.senderId
. Постгрес ищет столбец tm.senderId
в таблице direct_messages
и не находит его.
Вместо этого вы должны написать "tm"."senderId"
осторожно, чтобы указать таблицу / псевдоним и столбец отдельно.
1122 Это приводит к следующей ловушке, обсадной колонне. Если они не указаны в кавычках, Postgres будет использовать для вас строчные столбцы и имена таблиц.
test=# create table direct_messages ( senderId integer );
CREATE TABLE
test=# \d direct_messages
Table "public.direct_messages"
Column | Type | Collation | Nullable | Default
----------+---------+-----------+----------+---------
senderid | integer | | |
( Обратите внимание, что даже описание таблицы "public.direct_messages"
вводит в заблуждение. )
И оно будет делать то же самое для таблиц и столбцов без кавычек в запросах.
test=# select * from direct_messages tm where tm.sEnDerID is not null;
senderid
----------
(0 rows)
Но если вы процитируете их, он будет искать точное совпадение.
test=# select * from direct_messages tm where tm."sEnDerID" is not null;
ERROR: column tm.sEnDerID does not exist
LINE 1: select * from direct_messages tm where tm."sEnDerID" is not ...
test=# select * from direct_messages tm where tm."senderId" is not null;
ERROR: column tm.senderId does not exist
LINE 1: select * from direct_messages tm where tm."senderId" is not ...
^
HINT: Perhaps you meant to reference the column "tm.senderid".
test=# select * from direct_messages tm where tm."senderid" is not null;
senderid
----------
(0 rows)
В вашем запросе нет двусмысленных имен столбцов, поэтому удалите двойные кавычки.
SELECT *
FROM direct_messages tm
LEFT JOIN users tu ON tm.senderId = tu.id
WHERE tm.createdAt
ORDER BY created_at DESC
LIMIT 1;
(Дополнительное примечание: смешивать смешивание camelCase createdAt
и snake_case created_at
. Выберите один стиль для проекта и придерживайтесь его.)
5.3.1 из Стандарта имеют "Адрес объекта неполного типа, может быть взят, но если полный тип того объекта является типом класса, который объявляет operator& () как функция членства, тогда поведение не определено (и никакая диагностика не требуется)".
я не знал это также, но как другой плакат указал, легко видеть, как это могло заставить компилятор генерировать неправильный код.
Я не услышал о нем также, но это дает потенциально запутывающие результаты для того же кода прежде и после перегрузки:
#include <iostream>
class Foo;
void bar (Foo& foo) {
std::cout << &foo << std::endl;
}
class Foo {
public:
bool operator & () { return true; }
};
void baz (Foo& foo) {
std::cout << &foo << std::endl;
}
int main () {
Foo foo;
bar(foo);
baz(foo);
return 0;
}
вывод:
0x7fff092c55df
1
, Хотя существуют другие причины, почему Вы не сделали бы, это так или иначе - перегружающий адрес - не играет приятно с stl или большим количеством общего кода.
Из-за способности перегрузить operator& библиотека повышения предлагает удобный шаблон addressof () для заботы о нахождении действительного адреса класса. Не то, чтобы я предлагаю Вас перегрузка operator& но если Вы должны, справка доступна.
Я думаю, что оператор не точен. Как другие ответы, я предполагаю здесь. Во-первых, я предполагаю, что они обращаются к унарный operator& и не двоичный operator& . Это:
int x = 5;
int* p = &x; // unary &
if (x & 1) // binary &
можно передать, объявляют любой класс, который Вы хотите. Однако, если перегрузки класса унарный operator& и Вы называете унарный operator& на указателе на один из тех объектов Вы, вероятно, получите непоследовательное поведение (иногда, Вы просто получите адрес, и иногда Вы будете называть перегруженный метод). Это могло легко превратиться во что-то почти невозможное для отладки.
<час>я - довольный вызов в суд, на самом деле посмотрел на стандарт и не просто предположил.
Формулировка неясна, можно, конечно, передать, объявляют класс - но правило, очевидно, занимает позицию, что Вы "не были должны" где перегрузки класса operator&
.
Подобные правила также присутствуют в других стандартах кодирования, например JSF (PDF) , правило 159 указывает, что operator&
не должен быть перегружен.
Отредактированный для составления комментариев:
Это - предположение, но одна из главных причин передать объявляет, должен быть в состоянии объявить указатели на тот класс. Компилятор должен сделать предположения о классе прежде, чем иметь определение - например, размер указателей.
- это возможный изменить размер T* путем перегрузки operator& для T? (РЕДАКТИРОВАНИЕ: Commentors - и я думаю не) - но
, Что предположение нарушено путем перегрузки operator& - как это изменяет класс?
Вот один путь.
я мог записать:
class A;
void f(A& x) {
A* xPointer = &x;
}
, Который имеет новое значение если operator& (), перегружается, чем если бы не, и компилятор может думать, что он может сгенерировать код для него, но это было бы неправильно.