Именованный формат

9 5
 
				
				select distinct top %8:d
				  %0:s.%2:s,
				  %0:s.%3:s
				from
				  %0:s
				  %1:s
				where
				  %0:s.%9:s = %1:s.%5:s
				  and %1:s.%4:s = '%7:s'
				  and %1:s.%6:s <> '%9:s'
				order by
				  %0:s.%3:s

Вместо эпиграфа

Каждый раз, когда мне приходиться смотреть на SQL-запросы, написанные по всем правилам и рекомендациям, я испытываю когнитивный диссонанс. В самом деле, глядя на бесконечные ряды позиционных аргументов формата, сложно понять, о чем идет речь.

Думаю, именно из-за невозможности понять, что делают даже не самые сложные запросы, появилась такая штука, как PreprocQuery(). Если она подойдет в конкретной ситуации - отлично. Но иногда хочется странного получить более легкий и, в то же время, более универсальный инструмент. Ведь форматирование применяется не только в SQL-запросах, но и во многих других местах.

Так есть ли выход из этой безнадежной ситуации. Оказывается, есть. И, как это ни странно, все же давно придумано за нас.

Если мы взглянем на такой язык, как Python, то увидим, что вместо позиционных аргументов формата "%5:s" используются именованные "%(Name)s". Вместо списка подстановок передается словарь (Dictionary), содержащий пары  "имя-значение".

Для ISBL наиболее близким типом будет именованный список IList. Правда такого же удобного создания словаря, как в Python, на ISBL не получится, но можно воспользоваться функциями CreateInitializedList или CreateCompletedList().

И тогда вместо

DATE_TIME_FORMAT = "%2:s.%1:s.%0:s %3:s:%4:s:%5:s" 
DateTimeStr = Format(DATE_TIME_FORMAT; 
  ArrayOf(Year; Month; Day; Hour; Minute; Second))

Можно будеть писать

DATE_TIME_FORMAT = "%(Day)s.%(Month)s.%(Year)s %(Hour)s:%(Minute)s:%(Second)s" 
DateTimeStr = NamedFormat(DATE_TIME_FORMAT; CreateInitializedList(ArrayOf( 
  ArrayOf("Year"; Year);
  ArrayOf("Month"; Month); 
  ArrayOf("Day"; Day); 
  ArrayOf("Hour"; Hour); 
  ArrayOf("Minute"; Minute); 
  ArrayOf("Second"; Second))))  

Подстановка получается несколько длиннее, но зато по строке формата понятно, что курил хотел сказать автор.

P.S. Реализация функции NamedFormat прилагается. NamedFormat.zip (3,56 Кб) (пакет для DIRECTUM 4.7 - IS-Builder 7.8.3).

P.P.S. Функция написана на регулярных выражениях и IStringList, поэтому в теории должна работать шустро даже на больших строках формата.

Арслан Абакаров

 

Из стандартного можно еще Replace использовать.

 

запрос = "SELECT $аргумент$

FROM

MBAnalit

WHERE

dop = $условие$"

запрос = Replace( запрос ; "$аргумент$"; аргумент )
 

Андрей Подкин
Из стандартного можно еще Replace использовать.
А я все думал, что ж я такого забыл? smiley
 
У нас ведь теперь Format() понимает еще и форматирование чисел, причем с разными хитрыми аргументами. Доработал функцию и обновил ссылку на пакет разработки.
 
А если делать только для строк - согласен, можно и Replace обойтись (правда тормозить будет на больших данных).
Андрей Куров

А я продолжаю пользоваться конструкциями вида

str = 'А здесь был ' & UserName & ", написал он о том, что '" &

      UserMessage & "' и уехал в " & UserCity

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

Но вот предложенный вариант решения этой проблемы языком Groovy с GStrings сегодня откровенно порадовал:

UserName = 'Петя'

UserCity = 'Ленинград'

UserMessage = 'Вы умеете читать'

str = 'А здесь был ${UserName}, он написал: "${UserMessage}" и уехал в ${UserCity}'

Вот такой вариант даже читается легче и пишется быстрее, чем первый мой вариант. Красота.

Авторизуйтесь, чтобы написать комментарий