How to add a udf who's parameter is a table name - apache-calcite

I want to add a udf to calcite. The udf's parameter is a table name, and it will return a varchar value. Are there any sample for this? Thanks.
My test sql is:
SELECT MYTEST22(a), MYTEST(a), MYTEST1(a), COUNT(*)
FROM alisis.table1
WHERE a=max_dt(alisis.table1)
GROUP BY MYTEST22(a),MYTEST(a),MYTEST1(a)
max_dt is the function I want to add.

I don't know what your want to do, could you make a clear explanation?
No function can accept table as parameter, the parameters must have certain type, String, Int or others. So constants and columns can be used as parameters. If your meaning is the table name as a parameter, the sql should be as follows:
SELECT MYTEST22(a), MYTEST(a), MYTEST1(a), COUNT(*)
FROM alisis.table1
WHERE a=max_dt('alisis.table1')
GROUP BY MYTEST22(a),MYTEST(a),MYTEST1(a)
As I known, all functions Calcite (version is 1.11) supported are defined at SqlStdOperatorTable. If you want to support other functions, you can implement a class that extends SqlStdOperatorTable, for example:
public class TestOperatorTable extends SqlStdOperatorTable {
private static volatile TestOperatorTable instance;
public static TestOperatorTable instance() {
if (instance == null) {
synchronized(TestOperatorTable.class) {
if (instance == null) {
instance = new TestOperatorTable();
// Use reflection to register the expressions stored in public fields.
instance.init();
}
}
}
return instance;
}
/** Follow add your functions */
public static SqlFunction LTRIM = new SqlTrimFunction("LTRIM");
}
SqlTrimFunction as follows:
public class SqlTrimFunction extends SqlFunction {
public SqlTrimFunction(String funcName) {
super(
funcName,
SqlKind.OTHER_FUNCTION,
ReturnTypes.VARCHAR_2000, // return type is String
InferTypes.FIRST_KNOWN,
OperandTypes.STRING, // parameter type is String
SqlFunctionCategory.STRING
);
}
}
When you create a SqlValidator, for example SqlValidatorImpl, you should use TestOperatorTable as its first parameter.

Related

C++ - How to reserve some class objects to only be instantiated by a certain class

I'm defining a unique_id_generator class, which is kind of, sort of a singleton i.e there is just one instance for a given type_id. There can be many different type_ids, but for a specific type_id, there is just one instance.
Now I want to make sure that type_id = 0 goes to a very specific class. Basically just that specific class can use type_id = 0 and then the rest can be used freely.
I'm wondering through which design pattern can I ensure that happens?
I don't want to control or govern type_ids given in general.
FYI, I'm already using a private constructor to block un-guarded instantiation of the class.
I can't control who instantiates a unique_id_generator first. Also based on design, I don't want to route requests for unique ids through the specific class which gets type_id = 0.
Any thoughts/advice is greatly appreciated.
The only solution I could think of is to define 2 instantiation methods. One public and one private as follows:
#define EXCLUSIVE_CNT 1
class UniqueID
{
public:
friend class MySpecialClass;
static UniqueID * GetInstance(int type_id)
{
assert(type_id >= EXCLUSIVE_CNT);
return Instantiate(type_id);
}
private:
int type_id_;
int seq_id_;
std::map<type_id, UniqueID*> type_to_obj_map_;
UniqueID(int type_id)
{
type_id_ = type_id;
seq_id_ = 0;
}
static UniqueID * GetExclusiveInstance(int type_id)
{
assert(type_id < EXCLUSIVE_CNT);
return Instantiate(type_id);
}
static UniqueID * Instantiate(int type_id)
{
if(type_to_obj_map_.find(type_id) == type_to_obj_map_.end())
{
type_to_obj_map_[type_id] = new UniqueID(type_id);
}
return type_to_obj_map_[type_id];
}
};

How to use a doctrine custom type in a dql where statement?

I use Spatie's enums in my symfony project and I made a custom DBAL type for those objects. When I save an enum object to the database, I save it in a special string format. The conversion function in my EnumType looks like this:
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
return get_class($value) . '::' . $value->getIndex() . '::' . $value->getValue();
}
So for example I have a transaction status enum that looks like this:
namespace App\Enum;
use Spatie\Enum\Enum;
/**
* #method static self failed()
* #method static self pending()
* #method static self completed()
*/
final class TransactionStatus extends Enum {}
And when I save it to the database it can turn into any one of these strings respectively:
App\Enum\TransactionStatus::0::failed
App\Enum\TransactionStatus::1::pending
App\Enum\TransactionStatus::2::completed
This helps my EnumType to know what enum to transform it back into. And the reason I use the index number in the string is because that helps with sorting.
Now this all works very well for fetching and saving my entities to the database. But when I try to use an enum in a where clause of a DQL statement, it doesn't work at all.
namespace App\Repository;
use App\Entity\Transaction;
use App\Enum\TransactionStatus;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
class TransactionRepository extends ServiceEntityRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, Transaction::class);
}
public function findByStatus(TransactionStatus $status)
{
return $this->createQueryBuilder('t')
->andWhere('t.status = :status')
->setParameter('status', $status)
->getQuery()->getResult();
}
}
Because for some reason doctrine ignores my conversion function and just uses the __toString() function that's built into Spatie's enum. So doctrine is looking for the string "pending" instead of "App\Enum\TransactionStatus::1::pending".
How do I make sure that my enums always get converted correctly in a DQL where clause?
Okay I found a way to do it, even though it is super hacky. I just check from where the __toString() method is called and if it's called from Doctrine's DBAL then I use the DB format of the enum.
namespace App\Enum;
use Spatie\Enum\Enum as BaseEnum;
abstract class Enum extends BaseEnum
{
public function __toString(): string
{
if (debug_backtrace()[1]['class'] === 'PDOStatement') {
return get_class($this) . "::$this->index::$this->value";
}
return parent::__toString();
}
}

Are Value objects associations possible?

I wonder whether it's possible to have relations between entities and value objects or if a third entity is mandatory as relation target. The purpose could be to flag different kind of entities with a common data structure that has it's own business logic. Any idea ?
Update :
Let's say I have a business object to model SCAP CPE namings :
<?php
namespace Scap\Cpe\Naming;
/**
* Cpe22 represents the naming convention in CPE Naming version 2.2
* Accepted values are only CPE URIs
*/
class Cpe22
{
protected $cpe;
public function __construct($cpe)
{
if (! preg_match('/[c][pP][eE]:\/[AHOaho]?(:[A-Za-z0-9\._\-~%]*){0,6}/', $cpe)) {
throw new InvalidNamingException();
}
$this->cpe = $cpe;
}
}
If I want to flag different kind of entities with this VO in a one-to-many way, I can think of 2 different ways :
Entities are directly related to VOs so that the relation identifiers could be the entities references and the VOs themselves (= key composed from referenced identifier and representative VO fields)
Entities are related to third entity types, that embed the VOs so that the relation identifiers are those third entities identifiers
So I wonder if only the second option is available or if the first can somehow be implemented.
You should use a custom mapping type for things like this. For example, it could look something like this:
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform
class Cpe22Type extends Type
{
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getVarcharTypeDeclarationSQL(array('length' => 250));
}
public function convertToPHPVale($value, AbstractPlatform $platform)
{
return new Cpe22($value);
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return (string) $value;
}
public function getName()
{
return 'cpe22';
}
public function requiresSQLCommentHint(AbstractPlatform $platform)
{
return true;
}
}
Obviously, you have to add a __toString() method to your Cpe22 class for this to work.
After registering the type (how you do this depends on your framework, in symfony for example you do it in config.yml) you can simply map your field as type cpe22:
/**
* #ORM\Column(name="my_cpe", type="cpe22")
*/
public $myCpe;

Should I expect Neo4jOperations#queryForObjects to work with #QueryResult POJOs?

Neo4jOperations#queryForObjects() doesn't seem to play well with #QueryResult POJOs - it always says that result set is empty.
Trying Neo4jOperations#queryForObjects - it says result is empty:
#Test
public void thisDoesNotWork() {
Iterable<ClassNodeIdAndName> result = neo4jOperations.queryForObjects(
ClassNodeIdAndName.class,
"MATCH (c:ClassNode) RETURN ID(c) AS id, c.name AS name",
new HashMap<>());
assertTrue(result.iterator().hasNext());
}
Trying Neo4jOperations#query - says result is NOT empty:
#Test
public void thisWorksFine() {
Result result = neo4jOperations.query(
"MATCH (c:ClassNode) RETURN ID(c) AS id, c.name AS name",
new HashMap<>());
assertTrue(result.iterator().hasNext());
}
Trying repository with #Query - says result is NOT empty:
#Test
public void thisWorksFineAsWell() {
List<ClassNodeIdAndName> classNodeIdsAndNames = classNodeRepository.getAllIdsAndNames();
assertFalse(classNodeIdsAndNames.isEmpty());
}
public interface ClassNodeRepository extends GraphRepository<ClassNode> {
#Query("MATCH (c:ClassNode) RETURN ID(c) AS id, c.name AS name")
List<ClassNodeIdAndName> getAllIdsAndNames();
}
#QueryResult
public class ClassNodeIdAndName {
public Long id;
public String name;
}
Documentation says that
Iterable queryForObjects(Class entityType,
entityType - The Class denoting the type of entity to return
But I'm confused whether I should look at type of entity or at for objects. If it's not supposed to handle #QueryResult, I would expect it to throw instead of returning no results.
I'm using spring-data-neo4j 4.1.3.RELEASE
#QueryResult is a Spring Data Neo4j concept that applies only to Spring Repositorys.
Neo4jOperations is a thin wrapper around the Neo4j OGM's Session class and consequently does not handle the concept of returning query result objects.
Also see: SDN 4 Session.query doesn't work for #QueryResult

Partial Mock or new class or what else?

I have a question about testing.
I have a class that returns anomalies. in this class I have two different method that simply returns two different types of anomalies and one that return all anomalies (of both types)
this is the example code:
public interface IAnomalyService
{
IList<Anomaly> GetAllAnomalies(object parameter1, object parameter2);
IList<Anomaly> GetAnomalies_OfTypeA(object parameter1);
IList<Anomaly> GetAnomalies_OfTypeB(object parameter2);
}
public class AnomalyService : IAnomalyService
{
public IList<Anomaly> GetAllAnomalies(object parameter1, object parameter2)
{
var lstAll = new List<Anomaly>();
lstAll.AddRange(GetAnomalies_OfTypeA(parameter1));
lstAll.AddRange(GetAnomalies_OfTypeB(parameter2));
return lstAll;
}
public IList<Anomaly> GetAnomalies_OfTypeA(object parameter1)
{
//some elaborations
return new List<Anomaly> { new Anomaly { Id = 1 } };
}
public IList<Anomaly> GetAnomalies_OfTypeB(object parameter2)
{
//some elaborations
return new List<Anomaly> { new Anomaly { Id = 2 } };
}
}
class Anomaly
{
public int Id { get; set; }
}
I've created the tests for the two method that retrieve the anomalies of type A and type B (GetAnomalies_OfTypeA and GetAnomalies_OfTypeB).
Now I want to test the function GetAllAnomalies but I'm not sure what I have to do.
I think I have to way for testing it:
1) declare GetAnomalies_OfTypeA and GetAnomalies_OfTypeB in class AnomalyService as virtual, make a mock of the Class AnomalyService, and using Moq I can set CallBase as true and mock the two method GetAnomalies_OfTypeA and GetAnomalies_OfTypeB.
2)move the method GetAllAnomalies in another class called AllAnomalyService (with interface IAllAnomalyService) and in its constructor I will pass an interface of IAnomalyService and after I can test the GetAllAnomalies mocking the IAnomalyService interface.
I'm new at unit testing, so I don't know which solution is better, if is one of the mines or another one.
Can you help me?
thank you
Luca
Mocking is a good tool when a class resists testing. If you have the source, mocking is often not necessary. Try this approach:
Create a factory which can return AnomalyServices with various, defined anomalies (only type A, only type B, both, none, only type C, ...)
Since the three types are connected in some way, you should check all three in each test. If only anomalies of type A are expected, you should check that GetAllAnomalies returns the same result as GetAnomalies_OfTypeA and GetAnomalies_OfTypeB returns an empty list.