You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +03:00 
			
		
		
		
	This patch is the columnstore-part of the task. Columnstore wanted to have previous 32 depth, so this patch aims at keeping the compatibility.
		
			
				
	
	
		
			214 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "functor_json.h"
 | 
						|
#include "functioncolumn.h"
 | 
						|
#include "constantcolumn.h"
 | 
						|
#include "json_lib.h"
 | 
						|
#include "rowgroup.h"
 | 
						|
using namespace execplan;
 | 
						|
using namespace rowgroup;
 | 
						|
 | 
						|
#include "dataconvert.h"
 | 
						|
 | 
						|
#include "jsonhelpers.h"
 | 
						|
using namespace funcexp::helpers;
 | 
						|
 | 
						|
namespace
 | 
						|
{
 | 
						|
static bool checkContains(json_engine_t* jsEg, json_engine_t* valEg)
 | 
						|
{
 | 
						|
  json_engine_t localJsEg;
 | 
						|
  bool isEgSet;
 | 
						|
 | 
						|
  switch (jsEg->value_type)
 | 
						|
  {
 | 
						|
    case JSON_VALUE_OBJECT:
 | 
						|
    {
 | 
						|
      json_string_t keyName;
 | 
						|
 | 
						|
      if (valEg->value_type != JSON_VALUE_OBJECT)
 | 
						|
        return false;
 | 
						|
 | 
						|
      localJsEg = *jsEg;
 | 
						|
      isEgSet = false;
 | 
						|
      json_string_set_cs(&keyName, valEg->s.cs);
 | 
						|
      while (json_scan_next(valEg) == 0 && valEg->state != JST_OBJ_END)
 | 
						|
      {
 | 
						|
        const uchar *keyStart, *keyEnd;
 | 
						|
 | 
						|
        DBUG_ASSERT(valEg->state == JST_KEY);
 | 
						|
        keyStart = valEg->s.c_str;
 | 
						|
        do
 | 
						|
        {
 | 
						|
          keyEnd = valEg->s.c_str;
 | 
						|
        } while (json_read_keyname_chr(valEg) == 0);
 | 
						|
 | 
						|
        if (unlikely(valEg->s.error) || json_read_value(valEg))
 | 
						|
          return false;
 | 
						|
 | 
						|
        if (isEgSet)
 | 
						|
          *jsEg = localJsEg;
 | 
						|
        else
 | 
						|
          isEgSet = true;
 | 
						|
 | 
						|
        json_string_set_str(&keyName, keyStart, keyEnd);
 | 
						|
        if (!findKeyInObject(jsEg, &keyName) || json_read_value(jsEg) || !checkContains(jsEg, valEg))
 | 
						|
          return false;
 | 
						|
      }
 | 
						|
 | 
						|
      return valEg->state == JST_OBJ_END && !json_skip_level(jsEg);
 | 
						|
    }
 | 
						|
    case JSON_VALUE_ARRAY:
 | 
						|
      if (valEg->value_type != JSON_VALUE_ARRAY)
 | 
						|
      {
 | 
						|
        localJsEg = *valEg;
 | 
						|
        isEgSet = false;
 | 
						|
        while (json_scan_next(jsEg) == 0 && jsEg->state != JST_ARRAY_END)
 | 
						|
        {
 | 
						|
          int currLevel, isScaler;
 | 
						|
          DBUG_ASSERT(jsEg->state == JST_VALUE);
 | 
						|
          if (json_read_value(jsEg))
 | 
						|
            return false;
 | 
						|
 | 
						|
          if (!(isScaler = json_value_scalar(jsEg)))
 | 
						|
            currLevel = json_get_level(jsEg);
 | 
						|
 | 
						|
          if (isEgSet)
 | 
						|
            *valEg = localJsEg;
 | 
						|
          else
 | 
						|
            isEgSet = true;
 | 
						|
 | 
						|
          if (checkContains(jsEg, valEg))
 | 
						|
          {
 | 
						|
            if (json_skip_level(jsEg))
 | 
						|
              return false;
 | 
						|
            return true;
 | 
						|
          }
 | 
						|
          if (unlikely(valEg->s.error) || unlikely(jsEg->s.error) ||
 | 
						|
              (!isScaler && json_skip_to_level(jsEg, currLevel)))
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
      /* else */
 | 
						|
      localJsEg = *jsEg;
 | 
						|
      isEgSet = false;
 | 
						|
      while (json_scan_next(valEg) == 0 && valEg->state != JST_ARRAY_END)
 | 
						|
      {
 | 
						|
        DBUG_ASSERT(valEg->state == JST_VALUE);
 | 
						|
        if (json_read_value(valEg))
 | 
						|
          return false;
 | 
						|
 | 
						|
        if (isEgSet)
 | 
						|
          *jsEg = localJsEg;
 | 
						|
        else
 | 
						|
          isEgSet = true;
 | 
						|
        if (!checkContains(jsEg, valEg))
 | 
						|
          return false;
 | 
						|
      }
 | 
						|
 | 
						|
      return valEg->state == JST_ARRAY_END;
 | 
						|
 | 
						|
    case JSON_VALUE_STRING:
 | 
						|
      if (valEg->value_type != JSON_VALUE_STRING)
 | 
						|
        return false;
 | 
						|
      /*
 | 
						|
         TODO: make proper json-json comparison here that takes excipient
 | 
						|
               into account.
 | 
						|
       */
 | 
						|
      return valEg->value_len == jsEg->value_len && memcmp(valEg->value, jsEg->value, valEg->value_len) == 0;
 | 
						|
    case JSON_VALUE_NUMBER:
 | 
						|
      if (valEg->value_type == JSON_VALUE_NUMBER)
 | 
						|
      {
 | 
						|
        double jsEgVal, valEgVal;
 | 
						|
        char* end;
 | 
						|
        int err;
 | 
						|
 | 
						|
        jsEgVal = jsEg->s.cs->strntod((char*)jsEg->value, jsEg->value_len, &end, &err);
 | 
						|
        ;
 | 
						|
        valEgVal = valEg->s.cs->strntod((char*)valEg->value, valEg->value_len, &end, &err);
 | 
						|
        ;
 | 
						|
 | 
						|
        return (fabs(jsEgVal - valEgVal) < 1e-12);
 | 
						|
      }
 | 
						|
      else
 | 
						|
        return false;
 | 
						|
 | 
						|
    default: break;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
    We have these not mentioned in the 'switch' above:
 | 
						|
 | 
						|
    case JSON_VALUE_TRUE:
 | 
						|
    case JSON_VALUE_FALSE:
 | 
						|
    case JSON_VALUE_NULL:
 | 
						|
  */
 | 
						|
  return valEg->value_type == jsEg->value_type;
 | 
						|
}
 | 
						|
}  // namespace
 | 
						|
 | 
						|
namespace funcexp
 | 
						|
{
 | 
						|
CalpontSystemCatalog::ColType Func_json_contains::operationType(FunctionParm& fp,
 | 
						|
                                                                CalpontSystemCatalog::ColType& /*resultType*/)
 | 
						|
{
 | 
						|
  return fp[0]->data()->resultType();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * getBoolVal API definition
 | 
						|
 */
 | 
						|
bool Func_json_contains::getBoolVal(Row& row, FunctionParm& fp, bool& isNull,
 | 
						|
                                    CalpontSystemCatalog::ColType& /*type*/)
 | 
						|
{
 | 
						|
  bool isNullJS = false, isNullVal = false;
 | 
						|
 | 
						|
  const auto& js = fp[0]->data()->getStrVal(row, isNullJS);
 | 
						|
  const auto& val = fp[1]->data()->getStrVal(row, isNullVal);
 | 
						|
  if (isNullJS || isNullVal)
 | 
						|
  {
 | 
						|
    isNull = true;
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  bool result = false;
 | 
						|
 | 
						|
  if (!arg2Parsed)
 | 
						|
  {
 | 
						|
    if (!arg2Const)
 | 
						|
    {
 | 
						|
      ConstantColumn* constCol = dynamic_cast<ConstantColumn*>(fp[1]->data());
 | 
						|
      arg2Const = (constCol != nullptr);
 | 
						|
    }
 | 
						|
    arg2Val = val;
 | 
						|
    arg2Parsed = arg2Const;
 | 
						|
  }
 | 
						|
 | 
						|
  initJSEngine(jsEg, getCharset(fp[0]), js);
 | 
						|
 | 
						|
  if (fp.size() > 2)
 | 
						|
  {
 | 
						|
    if (!path.parsed && parseJSPath(path, row, fp[2], false))
 | 
						|
      goto error;
 | 
						|
 | 
						|
    if (locateJSPath(jsEg, path))
 | 
						|
      goto error;
 | 
						|
  }
 | 
						|
 | 
						|
  initJSEngine(valEg, getCharset(fp[1]), arg2Val);
 | 
						|
 | 
						|
  if (json_read_value(&jsEg) || json_read_value(&valEg))
 | 
						|
    goto error;
 | 
						|
 | 
						|
  result = checkContains(&jsEg, &valEg);
 | 
						|
 | 
						|
  if (unlikely(jsEg.s.error || valEg.s.error))
 | 
						|
    goto error;
 | 
						|
 | 
						|
  return result;
 | 
						|
 | 
						|
error:
 | 
						|
  isNull = true;
 | 
						|
  return false;
 | 
						|
}
 | 
						|
}  // namespace funcexp
 |