广告
返回顶部
首页 > 资讯 > 数据库 >如何进行数据库中间件 MyCAT 源码分析
  • 727
分享到

如何进行数据库中间件 MyCAT 源码分析

2024-04-02 19:04:59 727人浏览 独家记忆
摘要

这篇文章将为大家详细讲解有关如何进行数据库中间件 MyCAT 源码分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1. 概述可能你在看到这个标题会小小的吃

这篇文章将为大家详细讲解有关如何进行数据库中间件 MyCAT 源码分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

1. 概述

可能你在看到这个标题会小小的吃惊,MyCAT 能使用 mongoDB 做数据节点。是的,没错,确实可以。

吼吼吼,让我们开启这段神奇的“旅途”。

本文主要分成四部分:

  1. 总体流程,让你有个整体的认识

  2. 查询操作

  3. 插入操作

2. 主流程

如何进行数据库中间件 MyCAT 源码分析

MyCAT Server 接收 Mysql Client 基于 mysql协议 的请求,翻译 sql 成 MonGoDB操作 发送给 MongoDB  Server。

MyCAT Server 接收 MongoDB Server 返回的 MongoDB数据,翻译成 MySQL数据结果 返回给 MySQL  Client。

这样一看,MyCAT 连接 MongoDB 是不是少神奇一点列。

如何进行数据库中间件 MyCAT 源码分析

Java数据库连接,(Java Database  Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun  Microsystems的商标。JDBC是面向关系型数据库的。

MyCAT 使用 JDBC 规范,抽象了对 MongoDB 的访问。通过这样的方式,MyCAT 也抽象了 SequoiaDB  的访问。可能这样说法有些抽象,看个类图压压惊。

如何进行数据库中间件 MyCAT 源码分析

是不是熟悉的味道。不得不说 JDBC 规范的精妙。

3. 查询操作

SELECT id, name FROM user WHERE name > '' ORDER BY _id DESC;

如何进行数据库中间件 MyCAT 源码分析

看顺序图已经很方便的理解整体逻辑,我就不多废话啦。我们来看几个核心的代码逻辑。

1、查询 MongoDB

// MongoSQLParser.java public MongoData query() throws MongoSQLException {    if (!(statement instanceof SQLSelectStatement)) {        //return null;        throw new IllegalArgumentException("not a query sql statement");    }    MongoData mongo = new MongoData();    DBCursor c = null;    SQLSelectStatement selectStmt = (SQLSelectStatement) statement;    SQLSelectQuery sqlSelectQuery = selectStmt.getSelect().getQuery();    int icount = 0;    if (sqlSelectQuery instanceof MySqlSelectQueryBlock) {        MySqlSelectQueryBlock mysqlSelectQuery = (MySqlSelectQueryBlock) selectStmt.getSelect().getQuery();         BasicDBObject fields = new BasicDBObject();         // 显示(返回)的字段        for (SQLSelectItem item : mysqlSelectQuery.getSelectList()) {            //System.out.println(item.toString());            if (!(item.getExpr() instanceof SQLAllColumnExpr)) {                if (item.getExpr() instanceof SQLAggregateExpr) {                    SQLAggregateExpr expr = (SQLAggregateExpr) item.getExpr();                    if (expr.getMethodName().equals("COUNT")) { // TODO 待读:count(*)                        icount = 1;                        mongo.setField(getExprFieldName(expr), Types.BIGINT);                    }                    fields.put(getExprFieldName(expr), 1);                } else {                    fields.put(getFieldName(item), 1);                }            }         }         // 表名        SQLTableSource table = mysqlSelectQuery.getFrom();        DBCollection coll = this._db.getCollection(table.toString());        mongo.setTable(table.toString());         // WHERE        SQLExpr expr = mysqlSelectQuery.getWhere();        DBObject query = parserWhere(expr);         // GROUP BY        SQLSelectGroupByClause groupby = mysqlSelectQuery.getGroupBy();        BasicDBObject gbkey = new BasicDBObject();        if (groupby != null) {            for (SQLExpr gbexpr : groupby.getItems()) {                if (gbexpr instanceof SQLIdentifierExpr) {                    String name = ((SQLIdentifierExpr) gbexpr).getName();                    gbkey.put(name, Integer.valueOf(1));                }            }            icount = 2;        }         // SKIP / LIMIT        int limitoff = 0;        int limitnum = 0;        if (mysqlSelectQuery.getLimit() != null) {            limitoff = getSQLExprToInt(mysqlSelectQuery.getLimit().getOffset());            limitnum = getSQLExprToInt(mysqlSelectQuery.getLimit().getRowCount());        }        if (icount == 1) { // COUNT(*)            mongo.setCount(coll.count(query));        } else if (icount == 2) { // mapReduce            BasicDBObject initial = new BasicDBObject();            initial.put("num", 0);            String reduce = "function (obj, prev) { " + "  prev.num++}";            mongo.setGrouyBy(coll.group(gbkey, query, initial, reduce));        } else {            if ((limitoff > 0) || (limitnum > 0)) {                c = coll.find(query, fields).skip(limitoff).limit(limitnum);            } else {                c = coll.find(query, fields);            }             // order by            SQLOrderBy orderby = mysqlSelectQuery.getOrderBy();            if (orderby != null) {                BasicDBObject order = new BasicDBObject();                for (int i = 0; i < orderby.getItems().size(); i++) {                    SQLSelectOrderByItem orderitem = orderby.getItems().get(i);                    order.put(orderitem.getExpr().toString(), getSQLExprToAsc(orderitem.getType()));                }                c.sort(order);                // System.out.println(order);            }        }        mongo.setCursor(c);    }    return mongo; }

2、查询条件

// MongoSQLParser.java private void parserWhere(SQLExpr aexpr, BasicDBObject o) {    if (aexpr instanceof SQLBinaryOpExpr) {        SQLBinaryOpExpr expr = (SQLBinaryOpExpr) aexpr;        SQLExpr exprL = expr.getLeft();        if (!(exprL instanceof SQLBinaryOpExpr)) {            if (expr.getOperator().getName().equals("=")) {                o.put(exprL.toString(), getExpValue(expr.getRight()));            } else {                String op = "";                if (expr.getOperator().getName().equals("<")) {                    op = "$lt";                } else if (expr.getOperator().getName().equals("<=")) {                    op = "$lte";                } else if (expr.getOperator().getName().equals(">")) {                    op = "$gt";                } else if (expr.getOperator().getName().equals(">=")) {                    op = "$gte";                } else if (expr.getOperator().getName().equals("!=")) {                    op = "$ne";                } else if (expr.getOperator().getName().equals("<>")) {                    op = "$ne";                }                parserDBObject(o, exprL.toString(), op, getExpValue(expr.getRight()));            }        } else {            if (expr.getOperator().getName().equals("AND")) {                parserWhere(exprL, o);                parserWhere(expr.getRight(), o);            } else if (expr.getOperator().getName().equals("OR")) {                orWhere(exprL, expr.getRight(), o);            } else {                throw new RuntimeException("Can't identify the operation of  of where");            }        }    } }  private void orWhere(SQLExpr exprL, SQLExpr exprR, BasicDBObject ob) {    BasicDBObject xo = new BasicDBObject();    BasicDBObject yo = new BasicDBObject();    parserWhere(exprL, xo);    parserWhere(exprR, yo);    ob.put("$or", new Object[]{xo, yo}); }

3、解析 MongoDB 数据

// MongoResultSet.java public MongoResultSet(MongoData mongo, String schema) throws SQLException {    this._cursor = mongo.getCursor();    this._schema = schema;    this._table = mongo.getTable();    this.isSum = mongo.getCount() > 0;    this._sum = mongo.getCount();    this.isGroupBy = mongo.getType();     if (this.isGroupBy) {        dblist = mongo.getGrouyBys();        this.isSum = true;    }    if (this._cursor != null) {        select = _cursor.geTKEysWanted().keySet().toArray(new String[0]);        // 解析 fields        if (this._cursor.hasNext()) {            _cur = _cursor.next();            if (_cur != null) {                if (select.length == 0) {                    SetFields(_cur.keySet());                }                _row = 1;            }        }        // 设置 fields 类型        if (select.length == 0) {            select = new String[]{"_id"};            SetFieldType(true);        } else {            SetFieldType(false);        }    } else {        SetFields(mongo.getFields().keySet());//new String[]{"COUNT(*)"};        SetFieldType(mongo.getFields());    } }
  • 当使用 SELECT * 查询字段时,fields 使用***条数据返回的 fields。即使,后面的数据有其他 fields,也不返回。

4、返回数据给 MySQL Client

// JDBCConnection.java private void ouputResultSet(ServerConnection sc, String sql)        throws SQLException {    ResultSet rs = null;    Statement stmt = null;     try {        stmt = con.createStatement();        rs = stmt.executeQuery(sql);         // header        List<FieldPacket> fieldPks = new LinkedList<>();        ResultSetUtil.resultSetToFieldPacket(sc.getCharset(), fieldPks, rs, this.isspark);        int colunmCount = fieldPks.size();        ByteBuffer byteBuf = sc.allocate();        ResultSetHeaderPacket headerPkg = new ResultSetHeaderPacket();        headerPkg.fieldCount = fieldPks.size();        headerPkg.packetId = ++packetId;        byteBuf = headerPkg.write(byteBuf, sc, true);        byteBuf.flip();        byte[] header = new byte[byteBuf.limit()];        byteBuf.get(header);        byteBuf.clear();        List<byte[]> fields = new ArrayList<byte[]>(fieldPks.size());        for (FieldPacket curField : fieldPks) {            curField.packetId = ++packetId;            byteBuf = curField.write(byteBuf, sc, false);            byteBuf.flip();            byte[] field = new byte[byteBuf.limit()];            byteBuf.get(field);            byteBuf.clear();            fields.add(field);        }        // header eof        EOFPacket eofPckg = new EOFPacket();        eofPckg.packetId = ++packetId;        byteBuf = eofPckg.write(byteBuf, sc, false);        byteBuf.flip();        byte[] eof = new byte[byteBuf.limit()];        byteBuf.get(eof);        byteBuf.clear();        this.respHandler.fieldEofResponse(header, fields, eof, this);         // row        while (rs.next()) {            RowDataPacket curRow = new RowDataPacket(colunmCount);            for (int i = 0; i < colunmCount; i++) {                int j = i + 1;                if (MysqlDefs.isBianry((byte) fieldPks.get(i).type)) {                    curRow.add(rs.getBytes(j));                } else if (fieldPks.get(i).type == MysqlDefs.FIELD_TYPE_DECIMAL ||                        fieldPks.get(i).type == (MysqlDefs.FIELD_TYPE_NEW_DECIMAL - 256)) { // field type is unsigned byte                    // ensure that do not use scientific notation fORMat                    BigDecimal val = rs.getBigDecimal(j);                    curRow.add(StringUtil.encode(val != null ? val.toPlainString() : null, sc.getCharset()));                } else {                    curRow.add(StringUtil.encode(rs.getString(j), sc.getCharset()));                }            }            curRow.packetId = ++packetId;            byteBuf = curRow.write(byteBuf, sc, false);            byteBuf.flip();            byte[] row = new byte[byteBuf.limit()];            byteBuf.get(row);            byteBuf.clear();            this.respHandler.rowResponse(row, this);        }        fieldPks.clear();        // row eof        eofPckg = new EOFPacket();        eofPckg.packetId = ++packetId;        byteBuf = eofPckg.write(byteBuf, sc, false);        byteBuf.flip();        eof = new byte[byteBuf.limit()];        byteBuf.get(eof);        sc.recycle(byteBuf);        this.respHandler.rowEofResponse(eof, this);    } finally {        if (rs != null) {            try {                rs.close();            } catch (SQLException e) {            }        }        if (stmt != null) {            try {                stmt.close();            } catch (SQLException e) {            }        }    } }  // MongoResultSet.java @Override public String getString(String columnLabel) throws SQLException {    Object x = getObject(columnLabel);    if (x == null) {        return null;    }    return x.toString(); }

当返回字段值是 Object 时,返回该对象.toString()。例如:

mysql> select * from user order by _id asc; +--------------------------+------+-------------------------------+ | _id                      | name | profile                       | +--------------------------+------+-------------------------------+ | 1                        | 123  | { "age" : 1 , "height" : 100} |

4. 插入操作

如何进行数据库中间件 MyCAT 源码分析

// MongoSQLParser.java public int executeUpdate() throws MongoSQLException {    if (statement instanceof SQLInsertStatement) {        return InsertData((SQLInsertStatement) statement);    }    if (statement instanceof SQLUpdateStatement) {        return UpData((SQLUpdateStatement) statement);    }    if (statement instanceof SQLDropTableStatement) {        return dropTable((SQLDropTableStatement) statement);    }    if (statement instanceof SQLDeleteStatement) {        return DeleteDate((SQLDeleteStatement) statement);    }    if (statement instanceof SQLCreateTableStatement) {        return 1;    }    return 1; }  private int InsertData(SQLInsertStatement state) {    if (state.getValues().getValues().size() == 0) {        throw new RuntimeException("number of  columns error");    }    if (state.getValues().getValues().size() != state.getColumns().size()) {        throw new RuntimeException("number of values and columns have to match");    }    SQLTableSource table = state.getTableSource();    BasicDBObject o = new BasicDBObject();    int i = 0;    for (SQLExpr col : state.getColumns()) {        o.put(getFieldName2(col), getExpValue(state.getValues().getValues().get(i)));        i++;    }    DBCollection coll = this._db.getCollection(table.toString());    coll.insert(o);    return 1; }

关于如何进行数据库中间件 MyCAT 源码分析就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

您可能感兴趣的文档:

--结束END--

本文标题: 如何进行数据库中间件 MyCAT 源码分析

本文链接: https://www.lsjlt.com/news/67601.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何进行数据库中间件 MyCAT 源码分析
    这篇文章将为大家详细讲解有关如何进行数据库中间件 MyCAT 源码分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1. 概述可能你在看到这个标题会小小的吃...
    99+
    2022-10-19
  • 数据库中间件 MyCAT 源码分析 —— 调试环境搭建
    关注**微信公众号:【芋艿的后端小屋】**有福利:RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表RocketMQ / MyCAT / Sharding-JD...
    99+
    2022-10-18
  • 数据库中间件MyCat的示例分析
    这篇文章主要为大家展示了“数据库中间件MyCat的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“数据库中间件MyCat的示例分析”这篇文章吧。1、Myc...
    99+
    2022-10-18
  • Mycat中间件如何实现Mysql数据分片
    这篇文章主要介绍了Mycat中间件如何实现Mysql数据分片,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。架构图:机器规划:IP地址主机名角...
    99+
    2022-10-18
  • 如何进行数据库文件的空间分配
    本篇文章给大家分享的是有关如何进行数据库文件的空间分配,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。SQL Server日志文件出一系列日志记...
    99+
    2022-10-19
  • 如何进行NewSQL数据库TiDB的分析
    本篇文章给大家分享的是有关如何进行NewSQL数据库TiDB的分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。下面要介绍的是数据库领域的后起...
    99+
    2022-10-19
  • 如何进行分库分表中多数据源的事务处理
    这期内容当中小编将会给大家带来有关如何进行分库分表中多数据源的事务处理,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。系统经sharding改造之后,原来单一的数据库会演变...
    99+
    2022-10-19
  • Java异步编程中如何进行FutureTask源码分析
    本篇文章给大家分享的是有关Java异步编程中如何进行FutureTask源码分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Java的异步编程是一项非常常用的多线程技术。但之...
    99+
    2023-06-19
  • 如何使用Python中的数据分析库进行数据处理
    如何使用Python中的数据分析库进行数据处理人们越来越重视数据处理和分析的重要性。随着电子设备的不断普及和互联网的发展,我们每天都会产生大量的数据。要从这些海量的数据中提取有用的信息和洞察,就需要使用强大的工具和技术。Python作为一种...
    99+
    2023-10-22
    Python 数据分析 数据处理
  • 数据库数据文件如何进行分区转移
    数据库数据文件如何进行分区转移,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。由于之前同事没有对磁盘分区做规划,可以看到数据和系...
    99+
    2022-10-19
  • 如何进行数据库三大范式的分析
    这篇文章将为大家详细讲解有关如何进行数据库三大范式的分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一: 引言     &n...
    99+
    2022-10-19
  • 如何进行数据库的架构整体分析
    这期内容当中小编将会给大家带来有关如何进行数据库的架构整体分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。  很少谈架构方面的事情,主要是因为这确实是个对知识面和知识深...
    99+
    2022-10-19
  • 如何进行ADO.NET访问数据库技术分析
    如何进行ADO.NET访问数据库技术分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。着重解释ADO.NET访问数据库的步骤,在介绍ADO.NET访问数据库技术之前,首先让大家...
    99+
    2023-06-17
  • 如何在 Python 中使用 NumPy 库对文件中的数据进行统计分析?
    Python 是一种强大的编程语言,它拥有众多的库和工具可以帮助开发者更高效地完成任务。其中,NumPy 库是一款专门用于数值计算的库,在处理大量数据时可以提供高效的处理速度和良好的性能。 在本文中,我们将介绍如何使用 NumPy 库对文件...
    99+
    2023-11-04
    文件 关键字 numy
  • 如何进行SAP数据中心的分析
    今天就跟大家聊聊有关如何进行SAP数据中心的分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Jerry的前一篇文章企业数字化转型与SAP云平台介绍了SAP云平台在企业数字化转型中的...
    99+
    2023-06-04
  • PHP中如何进行数据分析处理?
    PHP是一门广泛应用于Web开发的语言,通常被用来构建动态的Web应用程序。随着数据驱动型应用程序的兴起,PHP在数据分析和处理方面也变得越来越重要。本文将介绍如何使用PHP进行数据分析处理,从数据的获取、存储、分析和可视化展示等方面进行讲...
    99+
    2023-05-14
    数据处理 数据统计 PHP数据分析
  • 如何进行生产数据库性能优化的分析
    这期内容当中小编将会给大家带来有关如何进行生产数据库性能优化的分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。需求:在钉钉群个人简介页面需要显示钉钉群名称和简介,每个群...
    99+
    2022-10-19
  • 数据库中如何按时间及ID进行分区表创建事例
    小编给大家分享一下数据库中如何按时间及ID进行分区表创建事例,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!Oracle表分区优点:1、 增强可用性:如果表的一个分区由于系统故障而不能使用,...
    99+
    2022-10-18
  • PHP中如何进行数据可视化和大数据分析?
    随着互联网和大数据的不断发展,数据分析和可视化已经成为了各种行业中非常重要的一个环节。而在现代Web应用程序中,PHP作为一种强大的服务器端语言,也提供了许多工具和库来帮助开发人员进行数据可视化和大数据分析。在本文中,我们将探讨如何使用PH...
    99+
    2023-05-22
    可视化 大数据 分析
  • 如何在Python中进行数据分析和挖掘
    如何在Python中进行数据分析和挖掘数据分析和挖掘是当今信息时代中不可或缺的关键技能。Python作为一种高级编程语言,具有丰富的数据处理和分析库,使得数据分析和挖掘变得更加简单和高效。本文将介绍如何在Python中进行数据分析和挖掘,并...
    99+
    2023-10-24
    Python 数据分析 挖掘
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作