Показать сообщение отдельно
Старый 28.09.2011, 17:36   #8  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5813 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Thumbs down Отключение функциональных индексов для Oracle убрали из ядра AX 2009
Цитата:
Сообщение от gl00mie Посмотреть сообщение
  • Действительно ли можно отключить хинтами использование функциональных индексов для Оракла в AX 2009?
  • Если да, то каким именно хинтом это можно сделать?
  • Где найти описание хинтов для AX 2009?
Я тут на досуге долго э... смотрел в хрустальный шар и увидел там ответы на эти вопросы. Ответы сводятся к тому, что штатно никакими хинтами отключить использование функциональных индексов в AX 2009 уже, в отличие от 3.0, нельзя. Ниже - краткая выжимка того, что удалось разглядеть в хрустальном шаре.
За использование функциональных индексов в ядре отвечают, насколько я смог разглядеть, три функции, чьи настоящие имена удалось-таки недавно узнать: MONOCASE_FIELD(), MONOCASE_LITERAL() и MONOCASE_PLACEHOLDER(). Вот, к примеру, как выглядит псевдокод функции MONOCASE_FIELD() в ax32serv.exe версии 3.0 KR3
X++:
char* MONOCASE_FIELD(char *pszBuf, CSqlFieldInfo *pSqlFieldInfo, bool forceMonoCase)
{
  if (gDatabaseCLI == DatabaseCLI::OCI)
  {
    if (  !forceMonoCase
       || !pSqlFieldInfo
       || ((fnGetSessionInfo()->getSqlSystem()->DatabaseHints >> 14) & 1)
       || ((fnGetSessionInfo()->getSqlSystem()->DatabaseHints >> 15) & 1) 
       )
    {
      strcpy(pszBuf, "%s");
    }
    else
    {
      sprintf(pszBuf, "SUBSTR(%s,1,%i)", "NLS_LOWER(%s)", pSqlFieldInfo->cbStringFieldBufSize - 1);
    }
  }
  else
  {
    if (!forceMonoCase || ((fnGetSessionInfo()->getSqlSystem()->DatabaseHints >> 15) & 1))
    {
      strcpy(pszBuf, "%s");
    }
    else
    {
      strcpy(pszBuf, "{fn LCASE(%s)}");
    }
  }
  return pszBuf;
}
Тут видно, что параметр forceMonoCase (название придумано мной) может быть "перекрыт" хинтом 0x8000 - при его использовании к строковому полю не будут применены никакие дополнительные функции. А теперь как эта же функция выглядит в ax32serv.exe версии 2009 SP1 RU7:
X++:
char* MONOCASE_FIELD(wchar_t *pwszBuf, unsigned int cnBufSize, struSqlFieldInfo *pSqlFieldInfo, bool forceMonoCase)
{
  int len;
  if (sql_dbcli != DatabaseCLI::OCI)
  {
    if (forceMonoCase)
    {
      return StringCchCopyW(pwszBuf, cnBufSize, L"{fn LCASE(%s)}");
    }
    return StringCchCopyW(pwszBuf, cnBufSize, L"%s");
  }
  if (!forceMonoCase || !pSqlFieldInfo)
  {
    return StringCchCopyW(pwszBuf, cnBufSize, L"%s");
  }
  len = pSqlFieldInfo->BaseType == Types::String ? (*&pSqlFieldInfo->cbStringFieldBufSize >> 1) - 1 : 0;
  return StringCchPrintfW(pwszBuf, cnBufSize, L"SUBSTR(%s,1,%i)", L"NLS_LOWER(%s)", len);
}
Все упоминания о хинтах пропали, и определяющим стал параметр forceMonoCase, а этот параметр во всех местах, где вызывается MONOCASE_FIELD(), определяется как
X++:
theDatabase()->DatabaseId == DatabaseId::Oracle
исключение составляет лишь SqlSystem.monocaseFmt() - здесь параметр forceMonoCase по умолчанию равен true, но может принять значение false, если при вызове этого метода указать параметр _considerSystemVariables == true и СУБД окажется НЕ Oracle. Аналогичная картина наблюдается для остальных двух функций. Вот псевдокод функции MONOCASE_LITERAL() в ядре 3.0 KR3
X++:
char* MONOCASE_LITERAL(char *pszBuf, bool forceMonoCase)
{
  if (gDatabaseCLI == DatabaseCLI::OCI)
  {
    if (forceMonoCase && !((fnGetSessionInfo()->getSqlSystem()->DatabaseHints >> 15) & 1))
    {
      return strcpy(pszBuf, "NLS_LOWER(%s)");
    }
  }
  else
  {
    if (forceMonoCase && !((fnGetSessionInfo()->getSqlSystem()->DatabaseHints >> 15) & 1))
    {
      return strcpy(pszBuf, "{fn LCASE(%s)}");
    }
  }
  return strcpy(pszBuf, "%s");
}
А вот она же в ядре 2009 SP1 RU7:
X++:
wchar_t* MONOCASE_LITERAL(wchar_t *pwszBuf, unsigned int cnBufSize, bool forceMonoCase)
{
  if (sql_dbcli != DatabaseCLI::OCI)
  {
    if (forceMonoCase)
    {
      return StringCchCopyW(pwszBuf, cnBufSize, L"{fn LCASE(%s)}");
    }
  }
  else
  {
    if (forceMonoCase)
    {
      return StringCchCopyW(pwszBuf, cnBufSize, L"NLS_LOWER(%s)");
    }  
  }	
  return StringCchCopyW(pwszBuf, cnBufSize, L"%s");
}
Вот MONOCASE_PLACEHOLDER() в ядре 3.0 KR3
X++:
void MONOCASE_PLACEHOLDER(char *pszBuf, void *a2, bool forceMonoCase, char *pszInOutBuf)
{
  // ...
  if (*pszInOutBuf)
  {
    v5 = *a2 + 1;
  }
  else
  {
    v5 = *(a2 + 4) + 1;
  }
  if (gDatabaseCLI == DatabaseCLI::OCI)
  {
    strcpy(pszInOutBuf), *pszInOutBuf ? "in" : "out");
    if (!forceMonoCase || ((fnGetSessionInfo()->getSqlSystem()->DatabaseHints >> 15) & 1))
      sprintf(pszBuf, ":%s%i", &pszInOutBuf, v5);
    else
      sprintf(pszBuf, "NLS_LOWER(:%s%i)", &pszInOutBuf, v5);
  }
  else
  {
    if (!forceMonoCase || ((fnGetSessionInfo()->getSqlSystem()->DatabaseHints >> 15) & 1))
      sprintf(pszBuf, "?");
    else
      sprintf(pszBuf, "{fn LCASE(?)}");
  }
}
И в ядре 2009 SP1 RU7:
X++:
void MONOCASE_PLACEHOLDER(wchar_t *a1, unsigned int *a2, void *pSqlField, void *pSqlMonocaseParamCnt, bool forceMonoCase, bool bIsIn)
{
  int v6;
  wchar_t v12;
  if (bIsIn)
  {
    ++*pSqlMonocaseParamCnt;
    v6 = *pSqlMonocaseParamCnt;
  }
  else
  {
    ++*(pSqlMonocaseParamCnt + 1);
    v6 = *(pSqlMonocaseParamCnt + 1);
  }
  if (sql_dbcli == DatabaseCLI::OCI)
  {
    StringCchCopyW(&v12, 4, bIsIn ? L"in" : L"out");
    StringCchPrintfExW(a1, *a2, &a1, a2, 0, forceMonoCase ? L"NLS_LOWER(:%s%i)" : L":%s%i", &v12, v6);
  }
  else
  {
    StringCchPrintfExW(a1, *a2, &a1, a2, 0, forceMonoCase ? L"{fn LCASE(?)}" : L"?");
  }
}
Таким образом, если в 3.0 (и, возможно, в 4.0 тоже!) существовал штатный, пусть и не документированный, способ отключить использование функциональных индексов при работе с СУБД Oracle, то в 2009-й из ядра его убрали, а все умоминания про такую возможность в конфигурационной утилите и в документаций - просто не подчищенные хвосты.
За это сообщение автора поблагодарили: shred (0), sukhanchik (15), Logger (18), lev (10), S.Kuskov (10).