快速上手

安装和使用 Swordfish

安装编译

位于 lib/abi_0/ 或 lib/abi_1/ 目录下的 libSwordfish.so 使用 g++-8.4.0 编译,推荐也使用 g++-8.4.0 来编译项目。如果使用 clang 编译器,请确保添加编译参数 -stdlib=libstdc++。

  1. 在编译前请先安装如下依赖库:

    zlib:执行 sudo apt-get install zlib1g-dev 进行安装。
  2. 执行以下指令进行编译:

    export LD_LIBRARY_PATH=/path/to/swordfish/lib/dependency:$LD_LIBRARY_PATH
    mkdir build
    cd build
    cmake ..
    make -j8

编译完成后,会在 build/bin 目录下生成可执行文件。

运行可执行文件

在 build/bin 目录下运行可执行文件之前,请确保该目录中包含了 dolphindb.dos, dolphindb.lic 和 dolphindb.cfg 文件。用户根据需求配置 dolphindb.cfg 文件中的相关项。具体配置项请参考 DolphinDB 配置文档

运行环境

main 函数代码体的开头,需要通过以下指令初始化 Swordfish 的运行环境:

DolphinDBLib::initializeRuntime();

main 函数代码体的结尾,需执行以下命令以销毁 Swordfish 运行环境:

DolphinDBLib::finalizeRuntime();

完整的代码结构如下:

# include "Swordfish.h"
int main() {
    DolphinDBLib::initializeRuntime();

    // 代码实现
    
    DolphinDBLib::finalizeRuntime();
    return 0;
}

对象创建

本节通过几个简单示例帮助用户了解如何在 Swordfish 中创建对象。参考 C++ 数据类型与形式了解更多对象创建和操作的方法。

创建标量

本节通过简单案例展示如何创建一个标量。

# include "Swordfish.h"

int main() {
    DolphinDBLib::initializeRuntime();
    // 创建一个 INT 标量
    Int *b = new Int(12);
    std::cout << b->getString() << std::endl;

    // 创建一个 STRING 标量
    String *str = new String("hello");

    std::cout << str->getString() << std::endl;

    // 创建一个 DOUBLE 标量
    Double *d = new Double(10);

    std::cout << d->getString() << std::endl;

    // 创建一个 DECIMAL32 对象,指定小数位数和原始数据
    Decimal<int> decimal1(2, 12345);  // 小数位数为 2,原始数据为 12345
        // 创建一个 DECIMAL64 对象,指定小数位数和原始数据
    Decimal<long long> decimal2(5, 88);  // 小数位数为 5,原始数据为 88

    // 创建一个时间类型
    Date *date1 = new Date(2024, 8, 14);

    std::cout << date1->getString() << std::endl;
    DolphinDBLib::finalizeRuntime();
    return 0;
}

创建向量

本节通过简单案例展示如何创建一个向量。

# include "Swordfish.h"

int main() {
    DolphinDBLib::initializeRuntime();
    // 创建一个 DOUBLE 类型向量
    VectorSP v1 = Util::createVector(DT_DOUBLE, 0, 100);
 
    // 添加元素
    std::vector<double> newData = {1.1, 2.2, 3.3};
    v1->appendDouble(newData.data(), newData.size());

    std::cout << v1->getDouble(1) << std::endl;

    // 创建一个 STRING 类型向量
    VectorSP v2 = Util::createVector(DT_STRING, 0);

    // 添加元素
    std::vector<string> newData2 = {"A", "B", "C"};
    v2->appendString(newData2.data(), newData2.size());

    std::cout << v2->getString() << std::endl;

    DolphinDBLib::finalizeRuntime();
    return 0;
}

创建元组

本节通过简单案例展示如何创建一个元组。

# include "Swordfish.h"
int main() {
    DolphinDBLib::initializeRuntime();
    // 创建一个元组
    VectorSP tp = Util::createVector(DT_ANY, 0);
    ConstantSP d1{new Double(1.1)};
    ConstantSP d2{new String("A")};
    //向元组追加 2 个元素
    tp->append(d1);
    tp->append(d2);
    //检查是否为元组,返回 1
    std::cout << tp->isTuple() << std::endl;
    DolphinDBLib::finalizeRuntime();
    return 0;
}

创建数据对

本节通过简单案例展示如何创建一个数据对。

# include "Swordfish.h"
int main() {
    DolphinDBLib::initializeRuntime();
    // 创建一个 DOUBLE 类型的数据对
    VectorSP p = Util::createPair(DT_DOUBLE);
    p->setInt(0, 1.1);
    p->setDouble(1, 3.6);
    //检查是否为数据对,返回 1
    std::cout << p->isPair() << std::endl;
    DolphinDBLib::finalizeRuntime();
    return 0;
}

创建矩阵

本节通过简单案例展示如何创建一个矩阵。

# include "Swordfish.h"
int main() {
    DolphinDBLib::initializeRuntime();
    int *rawData = new int[12]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    VectorSP m1 = Util::createMatrix(DT_INT, 4, 3, 12, 0, rawData);
    DolphinDBLib::finalizeRuntime();
    return 0;
}
/* output:
#0 #1 #2 #3
-- -- -- --
1  4  7  10
2  5  8  11
3  6  9  12
*/

创建字典

本节通过简单案例展示如何创建一个字典。

# include "Swordfish.h"
int main() {
    DolphinDBLib::initializeRuntime();
    // 创建一个字典
    DictionarySP d1 = Util::createDictionary(DT_INT, nullptr, DT_DOUBLE, nullptr);
    // 添加新的键值对
    ConstantSP k = Util::createConstant(DT_INT);
    k->setInt(1);
    ConstantSP v = Util::createConstant(DT_DOUBLE);
    v->setDouble(1.1);
    d1->set(k, v);
    k->setInt(2);
    v->setDouble(2.2);
    d1->set(k, v);
    std::cout << d1->getString() << std::endl;
    DolphinDBLib::finalizeRuntime();
    return 0;
}

创建集合

本节通过简单案例展示如何创建一个集合。

# include "Swordfish.h"
int main() {
    DolphinDBLib::initializeRuntime();
    // 创建一个集合
    SetSP s1 = Util::createSet(DT_INT, nullptr, 3);
    // 添加一个元素
    ConstantSP val = Util::createConstant(DT_INT);
    val->setInt(1);
    s1->append(val);
    val->setInt(2);
    s1->append(val);
    std::cout << s1->getString() << std::endl;
    DolphinDBLib::finalizeRuntime();
    return 0;
}

创建表

本节通过简单案例展示如何创建一个内存表。

# include "Swordfish.h"
int main() {
    DolphinDBLib::initializeRuntime();
    // 创建表
    std::string colName1 = "id";
    std::string colName2 = "val";
    std::vector<std::string> colNames = {colName1, colName2};
    std::vector<DATA_TYPE> colTypes = {DT_INT, DT_DOUBLE};
    TableSP tb1 = Util::createTable(colNames, colTypes, 0, 0);
    // 插入行
    std::string errMsg;
    ConstantSP id = Util::createConstant(DT_INT);
    ConstantSP val = Util::createConstant(DT_DOUBLE);
    for (auto i = 0; i < 10; ++i)
    {
    id->setInt(i);
    val->setDouble(i * 1.1);
    std::vector<ConstantSP> rowValues = {id, val};
    INDEX rowIdx = i;
    tb1->append(rowValues, rowIdx, errMsg);
    }
    if (errMsg.empty())
    {
    std::cout << tb1->getString() << std::endl;
    }
    else
    {
    std::cout << "insert rows failed! " << errMsg << std::endl;
    }
    DolphinDBLib::finalizeRuntime();
    return 0;
}

对象操作

本节以向量和表为例,简单展示如何进行对象操作。

向量操作

基于上节创建的 DOUBLE 类型向量 v1,进行一些向量操作。

  • 向量写入元素

    // 追加 1 个元素 1.5 
    v1->append(new Double(1.5));   // v1: [1.1,2.2,3.3,1.5]
    // 连续追加 3 个元素 2
    v1->append(new Double(2), 3);  // v1: [1.1,2.2,3.3,1.5,2,2,2]
  • 读取向量数据

    ConstantSP e1 = v1->get(0);     //e1 为 DT_DOUBLE 类型的标量,值是1.1
    double e2 = v1->getDouble(1);   //e2: 2.2  
  • 修改向量数据

    v1->set(1, new Double(100));  // vi: [1.1,100,3.3,1.5,2,2,2]
  • 删除向量数据

    // 删除指定索引的元素 
    ConstantSP index = Util::createIndexVector(3, 1);
    v1->remove(index);     vi: [1.1,100,3.3,2,2,2]
    
    // 删除最后 4 个元素
    v1->remove(4);    // [1.1,100]

表操作

基于上节创建的表 tb1,进行一些表操作。

  • 读取列数据

    // 读取第 1 列
    VectorSP col1 = tb1->getColumn(0);    // [0,1,2,3,4,5,6,7,8,9]
    
    // 读取 val 列
    VectorSP col2 = tb1->getColumn("val");   //[0,1.1,2.2,3.3,4.400000000000001,5.5,6.600000000000001,7.700000000000001,8.8,9.9]
  • 读取行数据

    // 读取第 1 行数据
    DictionarySP row = tb1->get(0);     
    std::cout << row->getString() << std::endl;  
    
    /* output:
    id->0
    val->0
    */
  • 向表中添加数据

    INDEX insertedRows;     
    std::string errorMsg;     
    VectorSP col0 = Util::createVector(DT_INT, 0);     
    VectorSP col1 = Util::createVector(DT_DOUBLE, 0);       
    col0->append(new Int(20));     
    col1->append(new Double(30.5));     
    vector<ConstantSP> values{col0, col1};     
    tb1->append(values, insertedRows, errorMsg); 
    std::cout << tb1->getString() << std::endl;  
    
    /* output:
    id val              
    -- -----------------
    0  0                
    1  1.1              
    2  2.2              
    3  3.3              
    4  4.400000000000001
    5  5.5              
    6  6.600000000000001
    7  7.700000000000001
    8  8.8              
    9  9.9              
    20 30.5    
    */
  • 修改某行数据

    VectorSP col1 = tb1->getColumn(0);    
    VectorSP col2 = tb1->getColumn("val");  
    
    // 通过修改每列的第 3 个元素,来修改表的第 3 行数据 
    col1->set(2, new Int(100));
    col2->set(2, new Double(32.597));
    
    std::cout << tb1->getString() << std::endl;   
    
    /* output:
    id  val               
    --- ------------------
    0   0                 
    1   1.1               
    100 32.597000000000001
    3   3.3               
    4   4.400000000000001 
    5   5.5               
    6   6.600000000000001 
    7   7.700000000000001 
    8   8.8               
    9   9.9   
    */

通用计算函数

Swordfish 定义了一系列通用计算函数,用于执行各种数据操作和计算,包括运算符、聚合函数、向量函数等。本节以 cumsummavgTopN 为例,简单介绍如何使用通用函数。

  • 使用计算函数前,需要引入头文件 OperatorImp.h。为方便函数调用,建议同时引入其命名空间。
    #include "OperatorImp.h"
    using namespace OperatorImp;
  • 调用 cumsum 计算向量元素的累加和

    # include "Swordfish.h"
    #include "OperatorImp.h"
    using namespace OperatorImp;
    int main() {
        DolphinDBLib::initializeRuntime();
        VectorSP v1 = Util::createVector(DT_INT,0);
        std::vector<int> newData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        v1->appendInt(newData.data(), newData.size());
        ConstantSP result = OperatorImp::cumsum(v1,Expression::void_);
        std::cout <<result->getString() << std::endl;
        DolphinDBLib::finalizeRuntime();
        return 0;
    }
    
  • 调用 mavgTopN 计算滑动窗口内前几个元素的平均值

    # include "Swordfish.h"
    #include "OperatorImp.h"
    using namespace OperatorImp;
    int main() {
        DolphinDBLib::initializeRuntime();
        // 构建待传入的参数
        SessionSP session = DolphinDBLib::createSession();
        VectorSP X =  Util::createVector(DT_INT,0);
        std::vector<int> newData = {1, 2, 3, 4, 5, 6, 7};
        X->appendInt(newData.data(), newData.size());
        VectorSP S =  Util::createVector(DT_DOUBLE,0);
        std::vector<double> newData1 = {0.3, 0.5, 0.1, 0.1, 0.5, 0.2, 0.4};
        S->appendDouble(newData1.data(), newData1.size());
        Int *window = new Int(4);
        Int *top = new Int(2);
        std::vector<ConstantSP> parameter = {X,S,window,top};
        // 调用 mavgTopN 计算结果并打印
        ConstantSP result = OperatorImp::mavgTopN(session->getHeap().get(),parameter);
        std::cout <<result->getString() << std::endl;
        DolphinDBLib::finalizeRuntime();
        return 0;
    }

状态函数

Swordfish 定义了一系列状态函数,可以用于响应式状态引擎中。这些状态通过增量计算,优化了计算性能。本节以 createMsumReactiveState 为例,介绍如何创建一个移动求和的状态算子。实现流程如下:

  1. 创建 DolphinDB 会话,以便在会话中执行 DolphinDB 的内置函数。

  2. 创建状态表,用于存储 val 和 msum 的值。

  3. 创建参数数组 args,第一个参数为 val 列的引用,第二个参数为窗口长度 3,用于计算移动求和。

  4. 使用 ReactiveStateFactory::createMsumReactiveState 创建一个移动求和的状态算子 msumReactiveState

  5. 向状态表中插入初始值(DBL_NMIN),表示移动求和的初始状态。

  6. 创建一个空的结果向量 msumResult,用于存储计算结果。

  7. 定义输入数据 valData,后续会对这些数值进行移动求和。

  8. 更新状态表,并调用 msumReactiveState->append() 方法进行增量计算。从状态表中获取当前索引的移动求和结果,并将其添加到结果向量 msumResult 中。

  9. 输出最终的移动求和结果。

#include "Swordfish.h"
int main() {
    DolphinDBLib::initializeRuntime();
    SessionSP session = DolphinDBLib::createSession();
    // Calculate msum(val, 3) context by sym
    vector<string> colNames = {"val", "msum"};
    vector<DATA_TYPE> colTypes = { DT_DOUBLE, DT_DOUBLE};
    TableSP stateTable = Util::createTable(colNames, colTypes, 0, 1);
    vector<ObjectSP> args(2);
    SQLContextSP context = new SQLContext();
    args[0] = new ColumnRef(context, "val");
    // Set window = 3
    args[1] = new Int(3); 
    // Set input column index in stateTable
    vector<int> inputColIndices = {0}; 
    // Set input column data type in stateTable
    vector<DATA_TYPE> inputColTypes = {DT_DOUBLE};
    // Set output column index in stateTable
    vector<int> outputColIndices = {1}; 
    // Create msum reactive state
    ReactiveStateSP msumReactiveState = ReactiveStateFactory::createMsumReactiveState(args, inputColIndices, inputColTypes, outputColIndices);
    msumReactiveState->setTable(stateTable);
    msumReactiveState->setSession(session);
    context->setTable(stateTable);
    INDEX rowInserted = 0;
    string errMsg;
    std::vector<ConstantSP> rowValues = {new Double(DBL_NMIN), new Double(DBL_NMIN)};
    if(!stateTable->append(rowValues, rowInserted, errMsg)){
        throw RuntimeException("Failed to append data to state table with error: " + errMsg);
    }
    msumReactiveState->addKeys(1);
    // Create result VectorSP
    VectorSP msumResult = Util::createVector(DT_DOUBLE, 0);
    // Create input data
    std::vector<double> valData = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};

    INDEX rows = valData.size();
    ConstantSP val = new Double();
    std::vector<ConstantSP> updateValue = {val};
    std::vector<string> updateColName = {"val"};
    VectorSP index = Util::createIndexVector(0,1);
    // Iterate through each element of valCol
    for(int i = 0; i < rows; i++){
        // Get the val element
        val->setDouble(valData[i]);
        if(!stateTable->update(updateValue, index, updateColName, errMsg)){
            throw RuntimeException("Failed to update state table with error: " + errMsg);
        }
        // Incrementally calculate msum
        msumReactiveState->append(session->getHeap().get(), index);
        // Get the result from stateTable for the current index
        ConstantSP res = stateTable->getColumn(1)->get(index);
        msumResult->append(res);
    }

    std::cout<<" msum result"<<std::endl;
    std::cout << msumResult->getString() << std::endl;
    DolphinDBLib::finalizeRuntime();
    return 0;
}