postgresql内核开发之add_months函数实战

Postgresql中,计算两个日期月份差值或年月日,实现Oracle中months_between、add_months的效果 Postgre SQL中,计算两个日期月份差值,实现ORACLE中MONTHS_BETWEEN的效果 阅读详情

postgresql内核内部函数实现详解

pg前文通过实现的helloworld入门,实际上就是实现了一个函数,但这个函数只有演示意义,也没有详细介绍函数实现细节,本文将详细介绍在postgresql内部如何完成一个函数的实现。
在oracle中,add_months函数能基于当前时间增加或减去几个月得出一个新日期,postgresql没有这样的函数,我们就以add_months有例子介绍下postgresql的函数增加方法。在C语言中,实现一个函数很简单,只要把函数主体实现就行,在其它文件中使用的话include头文件中声名就可以了,这两个步骤在postgresql内核中自然也要有,但还要增加一个动作,注册到pg_proc系统表中,pg_proc是postgresql中函数的系统表。
首先实现函数,因为是时间相关的函数,可以放到src/backend/utils/adt/date.c中,add_months_date和add_months_timestamp,头文件src/include/utils/date.h 增加声名,代码如下:

Datum
add_months_date(PG_FUNCTION_ARGS)
{
  DateADT    date = PG_GETARG_DATEADT(0);
  int    added_mon = PG_GETARG_INT32(1);
  struct pg_tm  tt;
  struct pg_tm * tm = &tt;
  bool   isLastDay = false;
  int    LastDay;
  int    year;
  int    mon;
  int    day;
  DateADT    result = 0;

  /* check range */
  if (DATE_NOT_FINITE(date))
  {
    PG_RETURN_DATEADT(date);
  }
  j2date((date + POSTGRES_EPOCH_JDATE), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
  year = tm->tm_year;
  mon = tm->tm_mon;
  day = tm->tm_mday;

  isLastDay = (day == day_tab[isleap(year)][mon - 1]);
  mon += added_mon;
  if (mon > 12)
  {
    year += ((mon - 1) / 12);
    mon = (((mon - 1) % 12) + 1);
  }
  else if (mon < 1)
  {
    year += ((mon / 12) - 1);
    mon = ((mon % 12) + 12);
  }

  LastDay = day_tab[isleap(year)][mon - 1];
  day = isLastDay ? LastDay : ((day > LastDay) ? LastDay : day);

  if (!IS_VALID_JULIAN(year, mon, day))
  {
    ereport(ERROR,
    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    errmsg("date out of range")));
  }
  result = (DateADT)(date2j(year, mon, day) - POSTGRES_EPOCH_JDATE);

  PG_RETURN_DATEADT(result);
}

Datum
add_months_timestamp(PG_FUNCTION_ARGS)
{
  Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
  int    added_mon = PG_GETARG_INT32(1);
  struct pg_tm  tt;
  struct pg_tm * tm = &tt;
  bool   isLastDay = FALSE;
  int    LastDay;
  int    year;
  int    mon;
  int    day;
  int    tz;

  fsec_t     fsec;
  Timestamp result = 0;


  if (TIMESTAMP_NOT_FINITE(timestamp))
  {
    PG_RETURN_TIMESTAMP(timestamp);
  }

  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
  {
    ereport(ERROR,
    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    errmsg("timestamp out of range")));
  }

  year = tm->tm_year;
  mon = tm->tm_mon;
  day = tm->tm_mday;

  isLastDay = (day == day_tab[isleap(year)][mon - 1]);
  mon += added_mon;
  if (mon > 12)
  {
    year += ((mon - 1) / 12);
    mon = (((mon - 1) % 12) + 1);
  }
  else if (mon < 1)
  {
    year += ((mon / 12) - 1);
    mon = ((mon % 12) + 12);
  }

  LastDay = day_tab[isleap(year)][mon - 1];
  day = isLastDay ? LastDay : ((day > LastDay) ? LastDay : day);

  tm->tm_year = year;
  tm->tm_mon = mon;
  tm->tm_mday = day;

  if (tm2timestamp(tm, fsec, NULL, &result) != 0)
  {
    ereport(ERROR,
    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    errmsg("timestamp out of range")));
  }

  PG_RETURN_TIMESTAMP(result);
}  

src/include/utils/date.h

extern Datum add_months_date(PG_FUNCTION_ARGS);
extern Datum add_months_timestamp(PG_FUNCTION_ARGS);

这里不对add_months函数内部逻辑深入,有兴趣的可以研究下oracle该函数表现对照下,重点在于完成了函数体实现,只要再注册到pg_proc中即可实现新增加函数。如何注册呢?
在src/include/catalog/pg_proc.h 新增代码如下:

DATA(insert OID = 9998 (add_months  PGNSP PGUID 12 1 0 0 0 f f f f t f i f 2 0 1082 "1082 23" _null_ _null_ _null_ _null_ _null_ add_months_date _null_ _null_ _null_));
DATA(insert OID = 9997 (add_months  PGNSP PGUID 12 1 0 0 0 f f f f t f i f 2 0 1114 "1114 23" _null_ _null_ _null_ _null_ _null_ add_months_timestamp _null_ _null_ _null_));
DATA(insert OID = 9996 (add_months  PGNSP PGUID 14 1 0 0 0 f f f f t f i f 2 0 1114 "1184 23" _null_ _null_ _null_ _null_ _null_ "select add_months($1::timestamp,$2)" _null_ _null_ _null_));

OK,全部需要增加的代码全部完成,编译,安装,重新初始化库,再运行测试如下:

postgres=# \d a
                 Table "public.a"
 Column |            Type             | Modifiers
--------+-----------------------------+-----------
 a      | date                        |
 b      | timestamp without time zone |


postgres=# select *from a;
     a      |             b
------------+----------------------------
 2016-12-04 | 2016-12-04 22:17:28.447829
 2016-02-28 | 2016-02-29 00:00:00
(2 rows)


postgres=# select a,add_months(a,3),b,add_months(b,4) from a;
     a      | add_months |             b              |         add_months
------------+------------+----------------------------+----------------------------
 2016-12-04 | 2017-03-04 | 2016-12-04 22:17:28.447829 | 2017-04-05 06:17:28.447829
 2016-02-28 | 2016-05-28 | 2016-02-29 00:00:00        | 2016-06-30 08:00:00
(2 rows)

add_months功能正常,至此一个内部函数增加完毕,下面再以提问的方式详细介绍下一些可能的疑问。
第一个问题,为什么要增加两个函数,不是只一个add_months吗?
事实上,一共增加了三个。这三个外部调用都是add_months函数,根据参数不相同实现了重载,在pg_proc.h注册时说明了这些参数。(后面还有详细说明)
第二个问题,注册是什么意思?
在模板库中插入记录,使任何库一创建就有。对于系统表来说,在它的头文件里有对这个系统表的详细定义说明,在这个头文件下面能按格式预置一些记录,这些记录在initdb时会插入到模板库的对应系统表中。具体来说,这些预置的记录,在编译过程中,会被perl脚本转换到postgres.bki中,这个bki文件在安装目录的share文件夹,当initdb时,会加载这个bki并解析成一条条sql运行,创建出一个个系统表,插入初始记录,把初始的信息准备好。有兴趣者可以看看initdb模块中 bootstrap_template1函数,初始化模块时第1件事就是加载postgres.bki文件翻译解析执行。
第三个问题,在pg_proc.h中插入的记录是什么含义?
以第一行为例详细说明如下:
DATA(insert OID = 9998 (add_months PGNSP PGUID 12 1 0 0 0 f f f f t f i f 2 0 1082 “1082 23” null null null null null add_months_date null null null));

  • 9998–OID使用内核中未使用的OID即可(src/include/catalog下unused_oids,可以显示未使用的oid) postgres内部预留了1W多个oid给系统用,选一个没有的就行,如果不知道哪些可用,在\src\include\catalog\ 下有个脚本文件unused_oids,运行一下就能找出哪些oid可用,但要这是一个linux脚本,需要在linux下运行。

  • add_months–函数名,我们在SQL中用的外部函数,但对应内部功能函数实现可能不止一个

  • PGNSP–函数所属的名字空间的OID,PGNSP即pg_catalog(oid=11),内置函数添加此值固定

  • PGUID–函数的拥有者OID,PGUID及initdb时指定用户(oid=10),内置函数添加此值固定

  • 12–实现语言或该函数的调用接口,内置函数使用12(internal),SQL用14,如第三个函数实现

  • 1–估计的执行代价,如果proretset为真,这是每行返回的代价

  • 0–估计的结果行数量(如果proretset为假,该值为0)

  • 0–可变数组参数的元素的数据类型,如果函数没有可变参数则为0

  • 0–调用该函数时可以通过此列指定的函数来简化

  • f–函数是否为一个聚集函数

  • f–函数是否为一个窗口函数

  • f–函数是一个安全性定义者(即,一个”setuid”函数)

  • f–该函数没有副作用。除了通过返回值,没有关于参数的信息被传播。任何会抛出基于其参数值的错误信息的函数都不是泄露验证的。

  • t–当任意调用函数为空时,函数是否会返回空值。在那种情况下函数实际上根本不会被调用。非”strict”函数必须准备好处理空值输入。

  • f–函数是否返回一个集合(即,指定数据类型的多个值)

  • i–provolatile说明函数是仅仅只依赖于它的输入参数,还是会被外部因素影响。值i表示”不变的”函数,它对于相同的输入总是输出相同的结果。值s表示”稳定的”函数,它的结果(对于固定输入)在一次扫描内不会变化。值v表示”不稳定的”函数,它的结果在任何时候都可能变化(使用v页表示函数具有副作用,所以对它们的调用无法得到优化)

  • f–函数类型(此项为我们开发过程中新增字段,表示函数类型,f代表函数,p代表过程,t代表触发器),postgresql内核没有此参数,可忽略

  • 2–输入参数的个数,对应后面的1082 23两个参数

  • 0–具有默认值的参数个数

  • 1082–返回值的数据类型

  • “1082 23”–函数参数的数据类型的数组,这只包括输入参数(含INOUT和VARIADIC参数),因此也表现了函数的调用特征 重载函数也凭这区别,如add_months函数,如果有多个,参数肯定不同,这个不同即可以是数量不同,也可以是类型不同,1082 23 就是代表类型,如下:

    postgres=# select oid,typname from pg_type where oid in (1082,23,1114,1184) ;
    oid  |   typname   
    ------+-------------
     23 | int4
    1082 | date
    1114 | timestamp
    1184 | timestamptz
    (4 rows)
  • _null_–函数参数的数据类型的数组,这包括所有参数(含OUT和INOUT参数)。但是,如果所有参数都是IN参数,这个域将为空。注意下标是从1开始 ,然而由于历史原因proargtypes的下标是从0开始

  • _null_–函数参数的模式的数组。编码为: i表示IN参数 , o表示OUT参数, b表示INOUT参数, v表示VARIADIC参数, t表示TABLE参数。 如果所有的参数都是IN参数,这个域为空。注意这里的下标对应着proallargtypes而不是proargtypes中的位置

  • _null_–函数参数的名字的数组。没有名字的参数在数组中设置为空字符串。如果没有一个参数有名字,这个域为空。注意这里的下标对应着proallargtypes而不是proargtypes中的位置

  • _null_–默认值的表达式树(按照nodeToString()的表现方式)。这是一个pronargdefaults元素的列表,对应于最后N个input参数(即最后N个proargtypes位置)。如果没有一个参数具有默认值,这个域为空

  • _null_–数据类型OID为了应用转换

  • add_months_date–函数处理者如何调用该函数。它可能是针对解释型语言的真实源码、一个符号链接、一个文件名或任何其他东西,这取决于实现语言/调用习惯,简单来说,就是add_months真正运行的东西,第一个是add_months_date ,第二个是调了add_months_timestamp函数,第三个是一个sql语句select add_months(1::timestamp,2)。虽然我们写sql语句时,并不是太关心相关的类型,但是在执行时,肯定是精确调某个函数来完成功能。第一个处理的是add_months(date,int), 第二个处理的是add_months(timestamp,int),第三个处理的是add_months(timestamptz,int),通过这样的方式实现sql函数重载。

  • _null_–关于如何调用函数的附加信息。其解释是与语言相关的

  • _null_–函数对于运行时配置变量的本地设置值

  • _null_–访问权限

第四个问题,Datum,PG_FUNCTION_ARGS,PG_GETARG_DATEADT,PG_RETURN_DATEADT,分别是什么东西?
Datum是通用的类型,存什么类型的值是什么由接收的人自己解析。PG_FUNCTION_ARGS是参数的宏,里面有函数的信息。PG_GETARG_DATEADT是取到前面的参数里的对应位置的参数值。PG_RETURN_DATEADT将值转成对应的类型返回,会将多余的字节清理掉。这些详细的可以看看代码,尤其PG_FUNCTION_ARGS的定义用法,对理解函数的实现有很大帮助。
ok,这次就到这,希望能对大家有所帮助。

CentOS 7 下 Bacula 企业级备份系统实战部署与灾备恢复 Bacula 是一款面向 Linux 服务器的开源企业级备份解决方案,其核心在于将备份从简单文件拷贝升级为具备调度、校验、审计与回滚能力的工程化体系。它基于 C/S 架构,通过 Director(调度中心)、Storage Daemon(存储管理)和 File Daemon(客户端代理)协同工作,天然适配 CentOS 7 的轻量环境与 SELinux 安全机制。相比 rsync+cron 的无版本快照或 duplicity 的脆弱增量链,Bacula 提供卷级校验、策略驱动的自动清理(prune)、多级保 阅读详情

相关推荐

Trae国内版:AI原生端到端开发范式落地实践

端到端开发是一种将需求、设计、编码、测试、部署全流程贯通的现代软件工程方法,其核心在于消除各环节间的信息衰减与工具割裂。随着大模型对中文工程语境理解能力提升,AI已从代码补全迈向项目级协同生成——尤其在深度适配国内开发基础设施(如微信API、阿里云OSS、国产数据库)和中文技术规范(如《阿里巴巴Java开发手册》)的前提下,AI编程工具开始真正支撑‘需求即服务’的快速交付。Trae作为首个实现原生集成、全链路闭环与本地化深度耦合的AI开发环境,标志着AI不再只是辅助工具,而是成为可信赖的协同工程伙伴。本文聚

aocaiti5781的博客 477

postgresql add_months

postgresql add_months

weixin_60333360的博客 2008

Python Playwright异步爬虫实战:逆向解析猎聘网高端职位数据

在数据驱动的时代,网络爬虫是获取公开信息的关键技术。其核心原理是通过程序模拟浏览器行为,向目标服务器发送请求并解析返回的HTML文档,从而提取结构化数据。这项技术的价值在于能够自动化、规模化地采集信息,为市场分析、竞品研究和趋势预测提供数据基础。在动态网页和反爬机制日益复杂的应用场景下,传统的静态爬虫库已力不从心。此时,需要借助更强大的浏览器自动化工具来穿透前端交互,直接获取渲染后的内容。本文聚焦于利用Playwright这一现代无头浏览器框架,结合Python异步编程,构建一个能够稳定、高效地逆向解析猎聘

culh2177的博客 635

PostgreSQL Oracle 兼容性之 - add_months

有网友反映PostgreSQL oraface的add_months在某些日期与Oracle 的add_months不一致。 查了一下Oracle 的开发手册,add_months是这样定义的, 如果当前日期是月末,或者目标月没有当前日期的,取最后一天。 例子 2015年2月28日是2月的最后一天,所以按照Oracle的计算方法,无论加减多少个月结...

weixin_33779515的博客 2838

CentOS 7 下部署 Bacula 备份系统实战指南

Bacula 是一款成熟的企业级开源备份软件,其核心架构包含 Director、Storage 和 File Daemon 三大组件,依赖可靠的元数据管理(Catalog)与安全的进程间通信。在 Linux 系统中,CentOS 7 因其长期支持、稳定内核和完善的 SELinux/iptables 机制,成为部署 Bacula 的高适配平台;而 MySQL 作为 Catalog 后端,可保障备份任务的 ACID 特性与高并发读写性能。本文聚焦于 CentOS 7 Minimal 环境下,基于 EPEL 官方

710

MINUS与EXCEPT:数据库集合差运算原理与生产级应用指南

集合差运算是关系代数中用于识别数据差异的核心操作,对应SQL标准中的EXCEPT(Oracle称MINUS),其本质是基于元组哈希比对的去重差集计算,而非算术减法。该操作天然支持跨表、跨库的数据一致性校验,在ETL对账、用户流失分析、风控设备比对等场景中具备O(n+m)时间复杂度优势。理解其哈希构建-探测-去重三阶段执行机制、NULL语义陷阱、列类型兼容性约束及内存模型,是规避ORA-01790、性能劣化与误判风险的关键。本文结合Oracle、PostgreSQL、ClickHouse等多引擎实践,解析如何

415

oracle pgsql 对比

直接上比较结果: 一.关于时间函数: 1.上月的今天: oracle SELECT add_months(sysdate,-1) from DUAL pgsql select (date_trunc('day', current_date - interval '0' day) + INTERVAL '-1 MONTH') lasttoday 上月今天的当前时刻 select to_char(now() + INTERVAL '-1 MONTH', 'YYYY-MM-DD HH24:

q_2372030362的博客 1170

Bacula开源备份架构原理与Linux服务器自主可控备份实践

Bacula是一款成熟稳定的开源网络备份系统,其核心在于三层守护进程(Director/Storage/File)解耦设计,通过配置驱动实现跨异构Linux环境的统一备份调度与数据完整性保障。它不依赖图形界面或云厂商锁定,以文本配置、Catalog元数据管理和存储抽象层支撑长期演进的备份策略。相比rsync+cron等轻量方案,Bacula提供增量链可重建、集中策略管控、精准文件级恢复等企业级能力;相较商业软件,它在老旧系统(如Ubuntu 14.04)中仍具备极低依赖、高兼容性与完全自主可控优势。本文基于

weixin_30378623的博客 341

《卸甲笔记》-PostgreSQL和Oracle的SQL差异分析之五:函数的差异(七)

PostgreSQL是世界上功能最强大的开源数据库,在国内得到了越来越多机构和开发者的青睐和应用。随着PostgreSQL的应用越来越广泛,Oracle向PostgreSQL数据库的数据迁移需求也越来越多。数据库之间数据迁移的时候,首先是迁移数据,然后就是SQL、存储过程、序列等程序中不同的数据库中数据的使用方式的转换。下面根据自己的理解和测试,写了一些...

weixin_34199335的博客 627

WSL2下用QEMU模拟ARM开发板:从编译uboot到调试全流程(附常见错误解决)

本文详细介绍了在WSL2环境下使用QEMU模拟ARM开发板的完整流程,包括uboot编译、内核调试等关键步骤。通过QEMU模拟vexpress-a9开发板,开发者可以高效搭建嵌入式开发环境,解决常见错误并提升开发效率。

solidity8miner的博客 287

MT6768平台Sensor Bring Up全流程实战:从驱动添加到问题排查(附避坑指南)

本文详细介绍了联发科MT6768平台Sensor Bring Up的全流程实战指南,从驱动添加、硬件配置到问题排查,提供了全面的避坑建议。内容涵盖环境准备、驱动文件集成、硬件接口配置、编译系统适配以及常见问题解决方案,帮助开发者高效完成传感器集成与调试工作。

weixin_30374009的博客 417

PostgreSQL 源码解读(180)- 内核研发#4(如何实现自定义系统函数)

本节以实现Oracle中的add_months函数为例介绍如何通过改造内核实现自定义系统函数. 一、基础知识 ...

862

Nest的限流方案

多维度限流(如 IP、用户 ID、接口级别、请求类型)可配置化(支持不同环境和接口动态配置)可观测性(接入日志、监控系统)高性能和分布式支持(Redis 限流器)与鉴权鉴权链路集成(结合 JWT、API Token)以下是一个“标准// 优先按用户ID限流,否则按IP在main.ts维度建议限流存储推荐 Redis 支持多实例限流 Key 设计支持 IP + 用户ID + 路由等多种维度限流策略精细化配置,接口粒度调整异常处理自定义响应体、日志告警观测性。

Bruce__taotao的博客 1197

SAP HANA时间函数实战指南:多时区、财务周期与实时窗口处理

时间函数是数据库处理日期与时间的核心能力,其本质是将物理时间戳映射为业务可理解的时间语义。在多时区协同、财务周期对齐等关键场景中,原生时间函数(如ADD_MONTHS、CONVERT_TZ)相比字符串模拟(如TO_VARCHAR+SUBSTRING)具备CPU指令级优化优势,性能差异可达10倍。SAP HANA的时间函数体系并非SQL标准的简单移植,而是围绕会话时区(SESSION_TIMEZONE)、类型安全(DATE vs TIMESTAMP)和业务规则(如月末智能回退)深度设计。它广泛应用于跨国报表开

weixin_34411563的博客 304

【华为OD机试真题 2025C卷】895、贪心歌手 | 机试真题+思路参考+代码解析 (C++、Java、Py、C语言、JS)

【华为OD机试真题 2025C卷】895、贪心歌手 | 机试真题+思路参考+代码解析 (C++、Java、Py、C语言、JS) 华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2025e卷,od机试,2025E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2025华为od,如何备战华

KJ.JK 965

Dify 第 7 篇 Dify 应用介绍 + 聊天助手&Agent 应用关键点说明

本文介绍了Dify应用的核心概念与使用方法。Dify是基于大模型构建的实际场景应用,提供API、WebApp和易用界面。包含5种应用类型:聊天助手、文本生成、Agent、对话流和工作流。创建方式有模板创建、空白应用和DSL文件三种。重点讲解了聊天助手和Agent应用的关键功能:聊天助手支持提示词优化、知识库引用、文件处理等;Agent应用则强调推理能力、工具调用和任务自动化。文章还详细介绍了应用的调试、发布和管理工具,为开发者提供了全面的应用构建指南。

甘蓝的专栏 1887

Python开发环境配置与IPython、Jupyter实战技巧

Python作为数据科学领域的主流语言,其开发环境配置直接影响工作效率。交互式编程环境通过实时反馈和可视化输出,极大提升了代码调试和数据分析效率。IPython作为增强型Python解释器,提供了Tab补全、对象自省和魔法命令等实用功能,特别适合快速原型开发。Jupyter Notebook则通过基于Web的交互界面和单元格执行模式,成为数据探索和教学演示的首选工具。在实际工程中,合理使用IPython的%timeit性能测试和Jupyter的%debug调试命令,能够显著提升Python项目的开发体验。本

weixin_33801856的博客 447

路径规划 | 图解Informed RRT*算法(附ROS C++/Python/Matlab仿真)

Informed RRT*算法针对RRT*算法进行了采样优化,用椭圆采样代替全局均匀采样,避免了RRT*算法搜索树上产生过多冗余分支的缺陷。本文图解Informed RRT*原理,并提供ROS C++/Python/Matlab三种实现加深理解

FRIGIDWINTER的博客 7502

Apache Arrow C++ 快速上手实战指南:安装链接、编码约定与四大核心教程

本篇技术指南围绕 Apache Arrow C++ 官方文档的 **Getting Started**([docs/source/cpp/getting_started.rst](https://link.gitcode.com/i/4034f8b7022c0bec821b7c2169268b0f))章节展开,系统讲解如何在自有 C++ 项目中集成 Arrow 库、遵循其编码约定,并通过四个循序渐

gitblog_01190的博客 325

零基础入门simulink建模仿真--基于Simulink的QPSK调制与解调仿真建模示例

QPSK是一种相位调制技术,将两个比特映射到一个符号上,每个符号对应四个可能的相位之一(0°、90°、180°、270°)。通过Simulink,我们可以通过模块化的建模方式实现QPSK的调制和解调过程,并观察信号在信道中的传输效果。通过本指南,我们介绍了如何基于Simulink搭建一个完整的QPSK调制与解调仿真模型,并进行仿真和性能评估。背景介绍:理解QPSK调制与解调的基本原理及其应用。所需工具和环境:列出进行QPSK仿真所需的工具和环境。步骤详解。

amy_mhd的博客 1311

51单片机入门指南-基于STC89C52(持续更新)

一、环境介绍 编程IDE: keil5 单片机型号: STC89C51/52 开发板: 普中科技的开发板 完整PDF资源下载地址:https://download.youkuaiyun.com/download/xiaolong1126626497/19785856 二、51单片机开发手册介绍 2.1 前言 51单片机是对所有兼容Intel 8031指令系统的单片机的统称。 该系列单片机的始祖是Intel的8004单片机,后来随着Flash rom技术的发展,8004单片机取得了长足的进展,成为应用最.

8802

国产数据库选型实战指南:从业务SQL出发的迁移决策方法论

数据库是支撑业务逻辑的核心数据服务层,其本质是事务处理、查询分析与高可用能力的有机组合。理解OLTP、HTAP、分布式事务等基础概念,掌握执行计划分析、分片键匹配、兼容性语法差异等关键技术原理,才能避免将迁移简化为‘换库’动作。国产数据库如PolarDB-X、TiDB、OceanBase、达梦DM8等,各自在强一致交易、实时分析、金融级容灾、Oracle兼容等维度具备差异化技术价值。实际应用中需聚焦真实业务场景——如电商秒杀依赖分库分表路由效率,社保结账依赖PL/SQL执行深度优化,GIS空间查询依赖扩展适

weixin_34185512的博客 296

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Debian 10 systemd-journald 日志集中化实战指南

日志集中化是现代系统可观测性的基石,其本质是将分散的文本日志升维为结构化、可查询、带元数据的事件流。基于 systemd 的 journald 天然支持 _SYSTEMD_UNIT、_HOSTNAME、PRIORITY 等12+维度元数据,使日志从‘grep大海捞针’转向‘数据库式精准检索’。在 Debian 10 这一长期稳定发行版中,通过 systemd-journal-remote 构建加密日志管道,不仅实现 TLS 安全传输与证书可信链管理,更支撑跨主机关联分析、服务级动态路由与合规性审计等高阶能力

weixin_33875839的博客 366

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

cn-math-taxonomy 本地部署全解:用自适应前置诊断,把高中错题一路追到没学会的小学知识点

孩子做错了「配方法」,真正缺的可能不是高二这册书,而是六年级的完全平方公式。cn-math-taxonomy 是一个数学(小学到高中)、英语(三年级到高中)与物理知识图谱的纯静态项目:你挑一个想检查的知识点,内置诊断工具每个点最多问 2 题,两题都错就沿先修关系一路回溯到小学,给出薄弱根因和从低年级排起的学习路径。家长可以用它摸底孩子的学习情况,老师可以用于备课和教研讨论。 ## 克隆即用:不需

gitblog_00709的博客 196

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

SpringBoot整合OceanBase实战:Oracle迁移避坑全指南

在数据库国产化替换浪潮下,如何从Oracle平滑迁移到OceanBase成为许多技术团队关注的焦点。OceanBase作为分布式数据库,提供了高度兼容Oracle模式的租户能力,但并非所有功能都完全一致。从驱动选择、连接配置到SQL方言、存储过程兼容性,每一步都可能隐藏陷阱。本文从SpringBoot项目整合OceanBase的视角出发,梳理了租户模式选型、驱动参数配置、SQL兼容性打磨、DBeaver连接技巧、数据迁移工具链以及灰度切换与回滚方案等关键技术点。通过合理的架构设计和充分的预演,能够有效降低迁

weixin_34408624的博客 372

Cube DuckDB Driver 深度解析:从连接初始化、查询执行到类型转换的完整实现指南

Cube(Cube Core)是开源的语义层(semantic layer),为 AI、BI 与嵌入式分析提供统一的数据访问能力。`@cubejs-backend/duckdb-driver` 是 Cube 生态中负责对接 DuckDB 的数据库驱动包,它让 Cube 可以通过 DuckDB 内嵌式分析引擎完成指标定义、预聚合(pre-aggregation)与查询下发。本文以该驱动的 [CHAN

gitblog_00438的博客 307
上一篇: postgresql内核开发之Oracle date类型兼容
下一篇: postgresql 内核开发之系统参数增加(上)
postgres20
博客等级 码龄10年 100粉丝 25原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值