| 119 | } |
| 120 | |
| 121 | static void ParseImpalaOptions(const StringVal& options, Document& document, |
| 122 | AiFunctions::AiFunctionsOptions& result) { |
| 123 | // If options is NULL or empty, return with defaults. |
| 124 | if (options.is_null || options.len == 0) return; |
| 125 | |
| 126 | if (document.Parse(reinterpret_cast<const char*>(options.ptr), options.len) |
| 127 | .HasParseError()) { |
| 128 | std::stringstream ss; |
| 129 | ss << "Error parsing impala options: " |
| 130 | << string(reinterpret_cast<const char*>(options.ptr), options.len) |
| 131 | << ", error code: " << document.GetParseError() << ", offset input " |
| 132 | << document.GetErrorOffset(); |
| 133 | throw std::runtime_error(ss.str()); |
| 134 | } |
| 135 | // Check for "api_standard" field. |
| 136 | if (document.HasMember(IMPALA_AI_API_STANDARD_FIELD) |
| 137 | && document[IMPALA_AI_API_STANDARD_FIELD].IsString()) { |
| 138 | const char* api_standard_value = document[IMPALA_AI_API_STANDARD_FIELD].GetString(); |
| 139 | if (gstrncasestr(IMPALA_AI_API_STANDARD_OPENAI, api_standard_value, |
| 140 | IMPALA_AI_API_STANDARD_OPENAI_LEN) != nullptr) { |
| 141 | result.api_standard = AiFunctions::API_STANDARD::OPEN_AI; |
| 142 | } else { |
| 143 | result.api_standard = AiFunctions::API_STANDARD::UNSUPPORTED; |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | // Check for "credential_type" field. |
| 148 | if (document.HasMember(IMPALA_AI_CREDENTIAL_TYPE_FIELD) |
| 149 | && document[IMPALA_AI_CREDENTIAL_TYPE_FIELD].IsString()) { |
| 150 | const char* credential_type_value = |
| 151 | document[IMPALA_AI_CREDENTIAL_TYPE_FIELD].GetString(); |
| 152 | if (gstrncasestr(IMPALA_AI_CREDENTIAL_TYPE_PLAIN, credential_type_value, |
| 153 | IMPALA_AI_CREDENTIAL_TYPE_PLAIN_LEN) != nullptr) { |
| 154 | result.credential_type = AiFunctions::CREDENTIAL_TYPE::PLAIN; |
| 155 | } else if (gstrncasestr(IMPALA_AI_CREDENTIAL_TYPE_JCEKS, credential_type_value, |
| 156 | IMPALA_AI_CREDENTIAL_TYPE_JCEKS_LEN) != nullptr) { |
| 157 | result.credential_type = AiFunctions::CREDENTIAL_TYPE::JCEKS; |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | // Check for "payload" field. |
| 162 | if (document.HasMember(IMPALA_AI_PAYLOAD_FIELD) |
| 163 | && document[IMPALA_AI_PAYLOAD_FIELD].IsString()) { |
| 164 | const char* payload_value = document[IMPALA_AI_PAYLOAD_FIELD].GetString(); |
| 165 | result.ai_custom_payload = std::string_view(payload_value); |
| 166 | // Check if payload exceeds the maximum allowed length of custom payload. |
| 167 | if (result.ai_custom_payload.length() > MAX_CUSTOM_PAYLOAD_LENGTH) { |
| 168 | std::stringstream ss; |
| 169 | ss << "Error: custom payload can't be longer than " << MAX_CUSTOM_PAYLOAD_LENGTH |
| 170 | << " bytes. Current length: " << result.ai_custom_payload.length(); |
| 171 | result.ai_custom_payload = std::string_view(); |
| 172 | throw std::runtime_error(ss.str()); |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | template <bool fastpath, AiFunctions::AI_PLATFORM platform> |
| 178 | StringVal AiFunctions::AiGenerateTextInternal(FunctionContext* ctx, |
no test coverage detected