Доступ к переменным локальной области действия из строки, используя синтаксический анализ или значение (KDB / Q) - PullRequest
0 голосов
/ 04 мая 2019

Следующие строки кода Q все выдают ошибку, потому что при синтаксическом анализе оператора "local" локальная переменная находится не в правильной области.

{local:1; value "local"}[]
{[local]; value "local"}[1]
{local:1; eval parse "local"}[]
{[local]; eval parse "local"}[1]

Есть ли способ получить локальную переменную из проанализированной строки?

Примечание: это упрощение реальной проблемы, с которой я сталкиваюсь, - написать функцию, которая выполняет запрос, принимая список столбцов, которые он должен возвращать. Я представляю, что готовый продукт выглядит примерно так:

getData:{[requiredColumns, condition]
    value "select ",(", " sv string[requiredColumns])," from myTable where someCol=condition"
    }

Параметр condition в этом запросе не распознается, и я понимаю, что могу добавить его значение, а не ссылаться на него внутри строки, но в реальном запросе используется множество локальных переменных, включая таблицы и т. Д., Поэтому это не так просто, как просто извлечь все переменные из строки перед вызовом value.

Я новичок в KDB и Q, поэтому, если у кого-то есть лучший способ добиться того же эффекта, я рад, что буду обучен правильному способу достижения этого результата в Q. Тем не менее, было бы интересно узнать о переменная доступ возможен, хотя.

Ответы [ 2 ]

3 голосов
/ 04 мая 2019

В первом примере вы правы, что local находится в неправильной области видимости, так как value ищет глобальную переменную local.

Один из способов обойти это - использовать пространство имен, которое будет определять переменную глобально, но доступ к нему можно получить только путем вызова этого пространства имен.В приведенном ниже модифицированном примере я определил local в .ns namespace

{.ns.local:1; value ".ns.local"}[]

Для проблемы, с которой вы сталкиваетесь при выборе, если requiredColumns - это список символов столбцов, вы можете просто использовать оператор take# чтобы выбрать их.

getData:{[requiredColumns] requiredColumns#myTable}

Для более сложных запросов с использованием переменных вам, возможно, придется использовать функциональную форму выбора, объясненную здесь .Это позволит вам включить переменные в предложение where и by оператора select

Тот же пример в функциональной форме будет (без предложения by, только select и where):

getData:{[requiredColumns;condition] requiredColumns:(), requiredColumns;
?[myTable;enlist (=;`someCol;condition);0b;requiredColumns!requiredColumns]}

Первая строка гарантирует, что requiredColumns является списком, даже если пользователь вводит имя одного столбца

2 голосов
/ 04 мая 2019

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

Ваша функция в основном правильная, просто требуется небольшая коррекция, чтобы добавить условие (я упоминал об этом ниже). Однако лучшим подходом было бы использовать функциональный выбор в этом случае.

Использование функционального выбора :

   q) t:([]id:`a`b; val:3 4)
   q) gd: {?[`t;enlist (=;`val;y);0b;((),x)!(),x]}
   q) gd[`id;3]   / for single column

Выход:

id
-
1
  q) gd[`id`val;3] / for multiple columns

Если ваш столбец условий имеет символ типа, введите значение условия, например:

  q) gd: {?[`t;enlist (=;`id;y);0b;((),x)!(),x]}
  q) gd[`id;enlist `a] 

Вы можете использовать parse, чтобы получить функциональную форму qsql запросов:

q) parse " select id,val from t where id=`a"
?
`t
,,(=;`id;,`a)
0b
`id`val!`id`val

Использование String concat (ваша функция):

q)getData:{[requiredColumns;condition] value "select ",(", " sv string[requiredColumns])," from t where id=", .Q.s1 condition}
q) getData[enlist `id;`a] / for single column
q) getData[`id`val;`a]  / for multi columns
...