Механизм работы dynamic query в контроллерах Salesforce Database.query('query string');

Механизм работы dynamic query в контроллерах Salesforce Database.query('query string');

Доброго времени суток уважаемые сеньоры и сеньориты. Прошу помощи в объяснении работы динамических запросов. Есть у меня контроллер с вот таким дефолтным конструктором

public ContactsManagerController() {

searchString ='';
queryString = 'SELECT Name, Email, OwnerId, Contact_Level__c, Created_Date__c, AccountId, CreatedById FROM Contact WHERE Name LIKE \'%'+searchString+'%\' LIMIT:LimitSize OFFSET:count';
totalRecs = [select count() from Contact];
getContacts();
}
и методами
public void getContacts() {

ContactList = DataBase.query(queryString);
}
public void Search(){

queryString = 'SELECT Name, Email, OwnerId, Contact_Level__c, Created_Date__c, AccountId, CreatedById FROM Contact WHERE Name LIKE \'%'+searchString+'%\' LIMIT:LimitSize OFFSET:count'; //магия и загадка тут
getContacts();
}

Собственно вопрос почему если не переопределить queryString(просто точно такая же строка как и в конструкторе) то новый запрос не выполняется? Я так понимаю построен Salesforce на Java а значит используется JIT компилятор... Тогда что за долбаная магия со строкой?
На странице вот такой вот код
<apex:pageBlock>

<apex:inputText value="{!searchString}" />
<apex:commandButton value = "Search" action="{!Search}" reRender="pg1"/>
</apex:pageBlock>

Так же хотелось бы узнать в какой момент значение введённое в inputText передается в searchString. В .NET за подобные вещи обычно отвечает какое либо событие... в Salesforce я так и не нашёл описание механизма работы..

Заранее благодарен за уделённое время и ответы.

когда пользовательский ввод в инпуте, привязанному к searchString (которая для работы с ВФ страницей должна быть переменной уровня контроллера (напрямую или через другую переменную), быть Паблик и иметь гет-сет), возвращается на сервер, то пройдя некоторые важные автоматические проверки, сразу же идет в searchString переменную, после чего вызывается требуемые метод, и он уже работает с новым значением в той переменной. никаких дополнительных действий не требуется. но если нужно как то более хитрее сделать гет-сет процесс, то просто пиши в нем что нужно

Den Brown
когда пользовательский ввод в инпуте, привязанному к searchString (которая для работы с ВФ страницей должна быть переменной уровня контроллера (напрямую или через другую переменную), быть Паблик и иметь гет-сет), возвращается на сервер, то пройдя некоторые важные автоматические проверки, сразу же идет в searchString переменную, после чего вызывается требуемые метод, и он уже работает с новым значением в той переменной. никаких дополнительных действий не требуется. но если нужно как то более хитрее сделать гет-сет процесс, то просто пиши в нем что нужно

public string searchString {get;set;}

string queryString;

ну так тем не менее если не переопределить queryString, то она не видит изменение в searchString. Такое ощущение как будто после присваивания searchString уже не как ссылка идёт в queryString, а как простое текстовое значение...

Kirill
Den Brown
когда пользовательский ввод в инпуте, привязанному к searchString (которая для работы с ВФ страницей должна быть переменной уровня контроллера (напрямую или через другую переменную), быть Паблик и иметь гет-сет), возвращается на сервер, то пройдя некоторые важные автоматические проверки, сразу же идет в searchString переменную, после чего вызывается требуемые метод, и он уже работает с новым значением в той переменной. никаких дополнительных действий не требуется. но если нужно как то более хитрее сделать гет-сет процесс, то просто пиши в нем что нужно

public string searchString {get;set;}

string queryString;

ну так тем не менее если не переопределить queryString, то она не видит изменение в searchString. Такое ощущение как будто после присваивания searchString уже не как ссылка идёт в queryString, а как простое текстовое значение...


потому что стринг - примитив, он по ссылке не работает

да и чтобы проще понять:
ты сделал
searchString = 'jopa'
а = '1' + searchString;
SystemDebug(a) => '1jopa'; это уже отдельная строка

а когда ты потом делаешь searchString = 'anus';
SystemDebug(a) => '1jopa'; потому что а определен как '1' + 'jopa'

рил толк синк эбаут ит
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_primitives.htm

Maxim Elets
рил толк синк эбаут ит
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_primitives.htm

Спасибо. Понял, но немного удивлен, что стринг самостоятельный тип, а не массив символов. Собственно отсутствие char тоже немного удивительно, как и наличие такого типа данных как Id

Maxim Elets

злой оффтоп, а как достать значение Id из pageblockTable?
Пробую вот так
<apex:pageBlockTable value="{!ContactList}" var="item" id="Table">


<apex:column >
<apex:commandLink value="DEL" action="{!DeleteRec}" reRender="Table">
<apex:param value="{!item.Id}" assignTo="{!DeleteId}"/>
</apex:commandLink>
</apex:column>
</apex:pageBlockTable>

DeleteId уже и стрингом пробовал и Id один чёрт не передаётся значение

UPD. Раступился ;)

Maxim Elets
рил толк синк эбаут ит
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_primitives.htm

‘Ни когда не стоит верить написанному иногда сомневайся, особенно фантастики’ блин....

Sergey Prishchepa
Maxim Elets
рил толк синк эбаут ит
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_primitives.htm

‘Ни когда не стоит верить написанному иногда сомневайся, особенно фантастики’ блин....

это ты к чему?

это я к тому что понятие примитива в Апекс очень сильно отличается от понятие Java и С# хотя бы лишь потому что не хранится в стеке.Помойму мы уже это обсуждали на форуме что все типы в Апекс это Nullable.

Sergey Prishchepa
это я к тому что понятие примитива в Апекс очень сильно отличается от понятие Java и С# хотя бы лишь потому что не хранится в стеке.Помойму мы уже это обсуждали на форуме что все типы в Апекс это Nullable.

primitive types в java, c#, apex это одно и тоже. В каждом языке конечно отличия в наборе этих типов, но в целом это одно и тоже
java Numeric primitives: short, int, long, float and double
java Textual primitives: byte and char.
java Boolean and null primitives: boolean and null.

apex Numeric primitives: decimal, double, integer, long
apex Textual primitives: blob, string, id.
apex Boolean: boolean.

и тд

да и как может отличаться понятие примитива? оно везде одинаковое: примитив это встроенный в каком то конкретном языке тип данных.

Sergey Prishchepa
все типы в Апекс это Nullable

А можно немного поподробнее?
Что-то меня эта фраза немного в затуп отправила.

Dmitry Shnyrev
Sergey Prishchepa
все типы в Апекс это Nullable

А можно немного поподробнее?
Что-то меня эта фраза немного в затуп отправила.

Скорее всего имелось ввиду,что в apex ,вроде как, все типы могут принимать null,т.е. в c# надо писать например int? i или int<nullable> i. А размещение в памяти это value &referance type. Т.е. если проводить анологию с c# то в apex все типы ссылочные. И хранятся в куче.

Dmitry Shnyrev
Sergey Prishchepa
все типы в Апекс это Nullable

А можно немного поподробнее?
Что-то меня эта фраза немного в затуп отправила.

это когда можно сделать Integer i = NULL;
в шарпе тоже так можно сделать, но только как int? i = NULL; int i = NULL - выдаст ошибку при компиляции

Ну в таком виде выглядет понятнее

Kirill
т.е. в c# надо писать например int? i или int<nullable> i

интересно. Опыт конечно с C# у меня никакой, но что-то не сталкивался с тем чтобы переменные у меня не принимали значения null. Наверно просто не успел столкнуться. Вот в Go вспоминаю. Там примитивные данные не могут непосредственно null, а содержат zero values в соотвествии со своими типами. Даже была большая проблема как смапить nullable колонки на переменные - там целый огород приходилось городить только для того чтобы переменная string могла быть string или null. Вот это было прям жесть. Хорошо что ни Apex ни JS ни Python такой фигней не страдают.

Maxim Elets
int i = NULL - выдаст ошибку при компиляции

А в рантайме?

Kirill
Т.е. если проводить анологию с c# то в apex все типы ссылочные

это не так, в apex есть reference & value type:
In Apex, all primitive data type arguments, such as Integer or String, are passed into methods by value. This means that any changes to the arguments exist only within the scope of the method. When the method returns, the changes to the arguments are lost.

Non-primitive data type arguments, such as sObjects, are also passed into methods by value. This means that when the method returns, the passed-in argument still references the same object as before the method call, and can’t be changed to point to another object. However, the values of the object’s fields can be changed in the method

Kirill
Скорее всего имелось ввиду,что в apex ,вроде как, все типы могут принимать null,т.е. в c# надо писать например int? i или int<nullable> i. А размещение в памяти это value &referance type. Т.е. если проводить анологию с c# то в apex все типы ссылочные. И хранятся в куче.

Жжешь я смотрю :)Все верно, еще можно добавить обычно примитивы хранятся в стеке. другое дело что операторы == переопределен по умолчанию и сравнивает значения, а если мы хотим сравнить ссылки выдает что так делать нельзя хотя всё хранится в кучи.
вся суть примитивов В Apex
Integer startingHeap = Limits.getHeapSize();
System.debug('StatingHeap=' + startingHeap);
static Integer myvalue = null;
static Integer myAnotherValue = 100000000;
Integer addedHeap = Limits.getHeapSize() - startingHeap;
System.debug('addedHeap=' + addedHeap);
хотя я думаю если поколупать equals можно чего нибудь интересное придумать.

Sergey Prishchepa
обычно примитивы хранятся в стеке

А можешь пояснить про какой стек ты ведешь беседу?

Sergey Prishchepa
а если мы хотим сравнить ссылки выдает что так делать нельзя

И какие ссылки у примитивов(которые value types) ты пытаешься сравнить?
Есть какой пример?

вся суть примитивов В Apex 

Integer startingHeap = Limits.getHeapSize();
System.debug('StatingHeap=' + startingHeap);
static Integer myvalue = null;
static Integer myAnotherValue = 100000000;
Integer addedHeap = Limits.getHeapSize() - startingHeap;
System.debug('addedHeap=' + addedHeap);

так в чем суть примитивов?

что-то я запутался

Maxim Elets
А можешь пояснить про какой стек ты ведешь беседу?
Классический

И какие ссылки у примитивов(которые value types) ты пытаешься сравнить?
да

Есть какой пример?
myvalue === myAnotherValue

так в чем суть примитивов?
то что всё они лежат в heap size потому как я понял у аpex другого хранилища нету.

Блин, чет я уже и русский перестал понимать
О чем вы тут вообще пишите?
Кучи сравнения ссылки.
Каким боком это относится к Apex?
Особенно про стек совсем нихера не понял. Мы сейчас что? разбираем устройство языка программирования APEX?
Я то думал что Apex транслируется/компилируется в обычный Java собственно так и работает. И сейчас вы пытаетесь сравнить Java и C#?

я просто скину тебе цитату из документации

Exact equality operator. If x and y reference the exact same location in memory, the expression evaluates to true. Otherwise, the expression evaluates to false.

так вот reference the exact same location in memory работает только для ссылочных типов, === работает только для ссылочных типов. Примитивы - это не ссылочные типы.

Account a = new Account(Name = 'a1');
Account b = a;
System.debug(LoggingLevel.ERROR, a == b); // true
b.Name = 'a2';
System.debug(LoggingLevel.ERROR, a == b); // true
System.debug(LoggingLevel.ERROR, a===b); // true

Integer i = 1;
Integer j = i;
System.debug(LoggingLevel.ERROR, i == j); // true

j = 2;
System.debug(LoggingLevel.ERROR, i == j); // false

Account - это ссылочный тип
Integer - нет

Maxim Elets
я просто скину тебе цитату из документации

Exact equality operator. If x and y reference the exact same location in memory, the expression evaluates to true. Otherwise, the expression evaluates to false.

так вот reference the exact same location in memory работает только для ссылочных типов, === работает только для ссылочных типов. Примитивы - это не ссылочные типы.

Account a = new Account(Name = 'a1');
Account b = a;
System.debug(LoggingLevel.ERROR, a == b); // true
b.Name = 'a2';
System.debug(LoggingLevel.ERROR, a == b); // true
System.debug(LoggingLevel.ERROR, a===b); // true

Integer i = 1;
Integer j = i;
System.debug(LoggingLevel.ERROR, i == j); // true

j = 2;
System.debug(LoggingLevel.ERROR, i == j); // false

Account - это ссылочный тип
Integer - нет

Dmitry Shnyrev
Блин, чет я уже и русский перестал понимать
О чем вы тут вообще пишите?
Кучи сравнения ссылки.
Каким боком это относится к Apex?
Особенно про стек совсем нихера не понял. Мы сейчас что? разбираем устройство языка программирования APEX?
Я то думал что Apex транслируется/компилируется в обычный Java собственно так и работает. И сейчас вы пытаетесь сравнить Java и C#?

Если apex транслируется на JVM (или как там у жабы рантайм называется) то не должна проходить ситуация что интовые поля равны null, но как я уже писал вышел есть варианты обхода этих случаев,
А что бы проверить ссылочные или нет нужно всего на всего посмотреть для кого доступен метод equals(). По сути не думаю, что, в salesforce имеет смысл заморачиваться с механизмами памяти.
Хотя я нубас фиг знает зачем учавствую в дискуссии))

Kirill
Хотя я нубас фиг знает зачем учавствую в дискуссии))

Мне наоборот твои ответы показались наиболее адекватными

Kirill
По сути не думаю, что, в salesforce имеет смысл заморачиваться с механизмами памяти.

так и есть!

Maxim Elets
Kirill
По сути не думаю, что, в salesforce имеет смысл заморачиваться с механизмами памяти.

так и есть!

Cчастливые люди, если у вас никогда не заканчивался CPU time и heap size :)

Sergey Prishchepa
Maxim Elets
Kirill
По сути не думаю, что, в salesforce имеет смысл заморачиваться с механизмами памяти.

так и есть!

Cчастливые люди, если у вас никогда не заканчивался CPU time и heap size :)

Как может кончится процессорное время?куча вообще только количеством оперативы ограничена. Что-то я вас не понял.

Sergey Prishchepa
Maxim Elets
Kirill
По сути не думаю, что, в salesforce имеет смысл заморачиваться с механизмами памяти.

так и есть!

Cчастливые люди, если у вас никогда не заканчивался CPU time и heap size :)

heap size && CPU валится только у тех кто плохокодит и попадает в рекурсии
это свойственно новичкам, людям которые просто отбивают бабки или людям которым похер
Мы же профессионалы своего дела! ;)

Kirill
Sergey Prishchepa
Maxim Elets
Kirill
По сути не думаю, что, в salesforce имеет смысл заморачиваться с механизмами памяти.

так и есть!

Cчастливые люди, если у вас никогда не заканчивался CPU time и heap size :)

Как может кончится процессорное время?куча вообще только количеством оперативы ограничена. Что-то я вас не понял.

у салесфорса свои лимиты
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm

Maxim Elets
Kirill
Sergey Prishchepa
Maxim Elets
Kirill
По сути не думаю, что, в salesforce имеет смысл заморачиваться с механизмами памяти.

так и есть!

Cчастливые люди, если у вас никогда не заканчивался CPU time и heap size :)

Как может кончится процессорное время?куча вообще только количеством оперативы ограничена. Что-то я вас не понял.

у салесфорса свои лимиты
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm

Maxim Elets
у салесфорса свои лимиты
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm

О как... а как сборщик муссора работает 6/12 метров так-то не большой размер, даже с учётом того, что веб-приложение на 90% работает на запросах в БД? Он чистит только объекты на которые нету ссылок или одному ктулху известно как это реализовано тут ?

Maxim Elets
Sergey Prishchepa
Maxim Elets
Kirill
По сути не думаю, что, в salesforce имеет смысл заморачиваться с механизмами памяти.

так и есть!

Cчастливые люди, если у вас никогда не заканчивался CPU time и heap size :)

heap size && CPU валится только у тех кто плохокодит и попадает в рекурсии
это свойственно новичкам, людям которые просто отбивают бабки или людям которым похер
Мы же профессионалы своего дела! ;)


а ты файлы когда нибудь парсил на 20MB файлы ?

Kirill
О как... а как сборщик муссора работает 6/12 метров так-то не большой размер, даже с учётом того, что веб-приложение на 90% работает на запросах в БД? Он чистит только объекты на которые нету ссылок или одному ктулху известно как это реализовано тут ?

У меня сложилось впчатление от слова никак,правда есть жесткий который включается только через суппорт.К сожалению заюзать его никак не смог,по этому делал все ручками блин...

Sergey Prishchepa
а ты файлы когда нибудь парсил на 20MB ?

Вы бы еще на 1Gb файлы парсили.

SF не предназначен для работы с большими объемами данных, парсингом, тем более для работы с файлами. Максимум что можно из него выжать - это залить и скачать/открыть файл. Для парсеров нужно использовать внешние сервисы.

Dmitry Shnyrev
Sergey Prishchepa
а ты файлы когда нибудь парсил на 20MB ?

Вы бы еще на 1Gb файлы парсили.

SF не предназначен для работы с большими объемами данных, парсингом, тем более для работы с файлами. Максимум что можно из него выжать - это залить и скачать/открыть файл. Для парсеров нужно использовать внешние сервисы.


это ты так думаешь!!! :)

проще начать рассказывать что ты новичок и ничего не понимаешь в СPU time и heap size или так делать нельзя, Wilder кажись вообще DOS подоходы использовал для файлов так что кто во что горазд....

Sergey Prishchepa
это ты так думаешь!!!

Я это знаю потому что сам не раз мучался с такими задачами на SF. Теперь знаю, что даже не стоит приступать к таким задачам потому что они изначально бомбы замедленного действия.
Если надо что-то спарсить/импортировать если нет возможности заюзать heroku,
то можно на худой сделать это через браузер в JS. Загружить файл, парсить и заливать пачками на SF.
Но я обычно делал еще проще - тупо ставил textarea куда любой тупой менеджер может тупо скопипастить содержимое файла а дальше все тоже самое - JS парсинг и заливка на SF.

Так что не по наслышке знаю - SF для заточен под работу с парсингом и большими объемами данных.

SF всего лишь CRM c небольшими возможностями кастомизации логики
Не стоит про это забывать.

Про Data Storage я вообще молчу - не понимаю как вообще реальный бизнес может работать с такими объемами данных. В нормальных прилагах с нормальным объемом данных этого Data Storage хватит на пару месяцев.

Sergey Prishchepa
а ты файлы когда нибудь парсил на 20MB файлы ?

сейчас бы парсить файлы в самом салесфорсе, а не использовать сторонний или даже свой написаный на питоне сервис + api...........
куда катится мир..

вы еще майнер под салесфорс напишите
у одного из наших клиентов:

Storage Type	Limit	Used	Percent Used

Data Storage 20.9 GB 24.1 GB 116%
File Storage 849.1 GB 343.7 GB 40%
Big Object Storage 1,000,000 0 0%

Maxim Elets
у одного из наших клиентов:

И интересно сколько этот клиент платит за это свое богатство.
У меня вот например сервер с Postgres и диском на 50GB = 10$/месяц.
При этом в Postgres нет того что запись в таблице занимает гарантированно 2Kb

https://www.digitalocean.com/pricing/

Maxim Elets
Sergey Prishchepa
а ты файлы когда нибудь парсил на 20MB файлы ?

сейчас бы парсить файлы в самом салесфорсе, а не использовать сторонний или даже свой написаный на питоне сервис + api...........
куда катится мир..

вы еще майнер под салесфорс напишите
у одного из наших клиентов:

Storage Type	Limit	Used	Percent Used

Data Storage 20.9 GB 24.1 GB 116%
File Storage 849.1 GB 343.7 GB 40%
Big Object Storage 1,000,000 0 0%

это уже сделали давно и кстати не так сложно учитывая возможности екма скрипт. :)

Sergey Prishchepa
это уже сделали давно и кстати не так сложно учитывая возможности екма скрипт.
Sergey Prishchepa

"Это сделали" это что сделали?
И что за "екма скрипт" это что-то новое в SF? Какой-то скриптовый/макросовый язык?

Dmitry Shnyrev
Sergey Prishchepa
это уже сделали давно и кстати не так сложно учитывая возможности екма скрипт.
Sergey Prishchepa

"Это сделали" это что сделали?
И что за "екма скрипт" это что-то новое в SF? Какой-то скриптовый/макросовый язык?

это жаваскрипт :)

Sergey Prishchepa
это уже сделали давно и кстати не так сложно учитывая возможности екма скрипт. :)

я вот тут загенерил txt в 8МБ и кажется мне что парсить этот жсон в браузере это прям садомазо, потому что браузер даже не хочет его открывать для view

а про парсинг 20 мб в браузере так вообще что-то из ряда фантастики

PS: сейчас проверим:)

Maxim Elets
PS: сейчас проверим:)

проверено, работает :)
но это был всего лишь JSON то есть тут особо ума не надо его открыть и распарсить, да и пишется этот парсер за 2 минуты.
интересно как оно будет работать с парсингом чего то не сильно структурированого :)

Вспомнил почему я скептически отношусь к парсингу больших файлов в браузере: как-то давно по работе мне приходилось конвертить JSON в CSV в браузере и JSON там был гораздо меньше 1мб, но времени занимало секунд 15:)

Kirill
Sergey Prishchepa
Maxim Elets
Kirill
По сути не думаю, что, в salesforce имеет смысл заморачиваться с механизмами памяти.

так и есть!

Cчастливые люди, если у вас никогда не заканчивался CPU time и heap size :)

Как может кончится процессорное время?куча вообще только количеством оперативы ограничена. Что-то я вас не понял.

Изучайте Salesforce лимиты ;)

Интересная информация? Помогите сайту, разместите ссылку в социальных сетях..