My library of UDF's

Here’s a UDF file I use a lot. Has a bunch of string manipulation functions that aren’t in the main language. This works in all v2 TigerGraph. I haven’t tried in v3 or v1.

Enjoy, and remember, sharp edges! Back stuff up before you change them, and be aware you might need to reinstall the product if you break things too badly.

/******************************************************************************
 * Copyright (c) 2015-2016, TigerGraph Inc.
 * All rights reserved.
 * Project: TigerGraph Query Language
 * udf.hpp: a library of user defined functions used in queries.
 *
 * - This library should only define functions that will be used in
 *   TigerGraph Query scripts. Other logics, such as structs and helper
 *   functions that will not be directly called in the GQuery scripts,
 *   must be put into "ExprUtil.hpp" under the same directory where
 *   this file is located.
 *
 * - Supported type of return value and parameters
 *     - int
 *     - float
 *     - double
 *     - bool
 *     - string (don't use std::string)
 *     - accumulators
 *
 * - Function names are case sensitive, unique, and can't be conflict with
 *   built-in math functions and reserve keywords.
 *
 * - Please don't remove necessary codes in this file
 *
 * - A backup of this file can be retrieved at
 *     <tigergraph_root_path>/dev_<backup_time>/gdk/gsql/src/QueryUdf/ExprFunctions.hpp
 *   after upgrading the system.
 *
 ******************************************************************************/

#ifndef EXPRFUNCTIONS_HPP_
#define EXPRFUNCTIONS_HPP_

#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <gle/engine/cpplib/headers.hpp>
#include <random>
#include <boost/regex.hpp>

/**     XXX Warning!! Put self-defined struct in ExprUtil.hpp **
 *  No user defined struct, helper functions (that will not be directly called
 *  in the GQuery scripts) etc. are allowed in this file. This file only
 *  contains user-defined expression function's signature and body.
 *  Please put user defined structs, helper functions etc. in ExprUtil.hpp
 */
#include "ExprUtil.hpp"

namespace UDIMPL {
  typedef std::string string; //XXX DON'T REMOVE

  /****** BIULT-IN FUNCTIONS **************/
  /****** XXX DON'T REMOVE ****************/
  inline int64_t str_to_int (string str) {
    return atoll(str.c_str());
  }

  inline int64_t float_to_int (float val) {
    return (int64_t) val;
  }

  inline string to_string (double val) {
    char result[200];
    sprintf(result, "%g", val);
    return string(result);
  }

// RH: first UDF - size of a string
  inline int64_t str_len (string str) {
    return (int64_t) str.size();
  }
// RH: second UDF - find a string in a string, and return where found it (or -1 if not found)
  inline int64_t str_find (string str1, string str2) {
    return (int64_t) str2.find(str1);
  }

  inline int64_t echo_int (int64_t echoThis) {
      return (int64_t) echoThis;
  }

// my random integer generator, using MT for fun. Random seed.
  inline int64_t rand_int (int minVal, int maxVal) {
      std::random_device rd;
      std::mt19937 e1(rd());
      std::uniform_int_distribution<int> dist(minVal, maxVal);
      return (int64_t) dist(e1);

  }

  // regex match, this one returns a boolean
  // based on code for tokenizer

  inline bool str_regex_match (string toCheck, string regEx) {
    bool res = false;
    // only performs the check when the input is valid
    try {
      res = boost::regex_match(toCheck, boost::regex(regEx));
    } catch (boost::regex_error err) {
      res = false;
    }
    return res;
  }


/*  Don't lose this parenthesis! */
}
/****************************************/

#endif /* EXPRFUNCTIONS_HPP_ */
3 Likes

So, I got challenged by a question elsewhere. How to filter a vertex based on whether a string is a member of vertex attribute which is a list or a set.

Here is my best shot. It is also a useful cheat sheet for getting lists/sets in and out, and iterating them.Not obvious to a C++ noob like myself. It uses the regex string function (defined in my library above), as I thought people might be searching for names in full names, for example.

// List filter, returns a list 
  inline ListAccum <string> regex_filter_list (ListAccum <string>& inBag , string regEx) {
    ListAccum <string> outBag;

for (int i=0; i < inBag.size(); i++){
    if (str_regex_match(inBag.get(i), regEx)) {
        outBag += inBag.get(i);
    }
}
return outBag;
  }

// Set filter, returns a set
  inline SetAccum <string> regex_filter_set (SetAccum <string>& inSet , string regEx) {
SetAccum <string> outSet;

for (auto& it :  inSet.data_) {
  if (str_regex_match(it, regEx)) {
    outSet += it;
  }
}
return outSet;
  }

An example test query:

CREATE QUERY tryFilterBag(string regex) FOR GRAPH MyGraph { 
  /* Write query logic here */ 
	ListAccum <STRING> @outList ;
	SetAccum <STRING> @outSet;
	
	bv = {BagVertex.*}; 
	
	bv = select bvv from bv:bvv
	POST-ACCUM 
	  bvv.@outList = regex_filter_list(bvv.myList, regex),
	  bvv.@outSet = regex_filter_set(bvv.mySet, regex);
      //HAVING bvv.@outList.size() > 0; // uncomment for direct filtration
	  
	cv = select cvv from bv:cvv
	WHERE cvv.@outList.size() > 0 AND cvv.@outSet.size() > 0;

  PRINT bv, cv; 
}
1 Like