首页 > 编程语言 >PG14:adminpack 插件源码分析

PG14:adminpack 插件源码分析

时间:2024-03-14 11:23:30浏览次数:33  
标签:rename 插件 fn3 fn2 text PG14 源码 pg file

adminpack 提供了大量支持功能,pgAdmin 和其他管理工具可以使用这些功能提供额外功能,例如远程管理服务器日志文件。默认情况下,只有数据库超级用户才能使用所有这些功能,但其他用户也可以使用 GRANT 命令使用这些功能。

我们先来看一下他支持的函数,可以通过 \dx+ adminpack 来进行查看

  • function pg_file_rename(text,text) 重命名文件
  • function pg_file_rename(text,text,text) 重命名文件,如果新文件存在,将将其命名为第三个参数的名字
  • function pg_file_sync(text) 文件刷入磁盘
  • function pg_file_unlink(text) 删除文件
  • function pg_file_write(text,text,boolean) 写文件
  • function pg_logdir_ls() 列出日志目录下的文件

pg_file_rename(text,text)

用于重命名文件,我们看一下 sql 代码

CREATE FUNCTION pg_catalog.pg_file_rename(text, text)
RETURNS bool
AS 'SELECT pg_catalog.pg_file_rename($1, $2, NULL::pg_catalog.text);'
LANGUAGE SQL VOLATILE STRICT;

这里我们看到两个参数版本的 pg_file_rename 直接调用来三参数版本的 pg_file_rename, 因此我们直接查看三参数版本的 SQL 代码

CREATE OR REPLACE FUNCTION pg_catalog.pg_file_rename(text, text, text)
RETURNS bool
AS 'MODULE_PATHNAME', 'pg_file_rename_v1_1'
LANGUAGE C VOLATILE;

这个 SQL 代码直接调用来 C 函数 pg_file_rename_v1_1 来实现文件重命名。

现在我们来看一下 C 函数 pg_file_rename_v1_1

Datum
pg_file_rename_v1_1(PG_FUNCTION_ARGS)
{
	text	   *file1;
	text	   *file2;
	text	   *file3;
	bool		result;

	if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
		PG_RETURN_NULL();

	file1 = PG_GETARG_TEXT_PP(0);
	file2 = PG_GETARG_TEXT_PP(1);

	if (PG_ARGISNULL(2))
		file3 = NULL;
	else
		file3 = PG_GETARG_TEXT_PP(2);

	result = pg_file_rename_internal(file1, file2, file3);

	PG_RETURN_BOOL(result);
}

这个代码中仅仅是判断参数是否为空,如果不为空,则获取参数,然后调用 pg_file_rename_internal 这个函数

static bool
pg_file_rename_internal(text *file1, text *file2, text *file3)
{
	char	   *fn1,
			   *fn2,
			   *fn3;
	int			rc;

	fn1 = convert_and_check_filename(file1);
	fn2 = convert_and_check_filename(file2);

	if (file3 == NULL)
		fn3 = NULL;
	else
		fn3 = convert_and_check_filename(file3);

	if (access(fn1, W_OK) < 0)
	{
		ereport(WARNING,
				(errcode_for_file_access(),
				 errmsg("file \"%s\" is not accessible: %m", fn1)));

		return false;
	}

	if (fn3 && access(fn2, W_OK) < 0)
	{
		ereport(WARNING,
				(errcode_for_file_access(),
				 errmsg("file \"%s\" is not accessible: %m", fn2)));

		return false;
	}

	rc = access(fn3 ? fn3 : fn2, W_OK);
	if (rc >= 0 || errno != ENOENT)
	{
		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_FILE),
				 errmsg("cannot rename to target file \"%s\"",
						fn3 ? fn3 : fn2)));
	}

	if (fn3)
	{
		if (rename(fn2, fn3) != 0)
		{
			ereport(ERROR,
					(errcode_for_file_access(),
					 errmsg("could not rename \"%s\" to \"%s\": %m",
							fn2, fn3)));
		}
		if (rename(fn1, fn2) != 0)
		{
			ereport(WARNING,
					(errcode_for_file_access(),
					 errmsg("could not rename \"%s\" to \"%s\": %m",
							fn1, fn2)));

			if (rename(fn3, fn2) != 0)
			{
				ereport(ERROR,
						(errcode_for_file_access(),
						 errmsg("could not rename \"%s\" back to \"%s\": %m",
								fn3, fn2)));
			}
			else
			{
				ereport(ERROR,
						(errcode(ERRCODE_UNDEFINED_FILE),
						 errmsg("renaming \"%s\" to \"%s\" was reverted",
								fn2, fn3)));
			}
		}
	}
	else if (rename(fn1, fn2) != 0)
	{
		ereport(ERROR,
				(errcode_for_file_access(),
				 errmsg("could not rename \"%s\" to \"%s\": %m", fn1, fn2)));
	}

	return true;
}

这个函数的整体逻辑为,先将 text* 类型的数据转换为 char* 类型的数据,会在这个转换的过程中处理一些路径相关和权限验证的问题。

然后先判断一下 fn1 是不是存在,如果不存在那肯定是没法重命名的,然后判断一下 fn3 是不是为空,并且 fn2 是不是存在,如果不存在,那么将 fn2 重命名为 fn3 也会失败。

然后判断一下 fn3 是不是存在,如果存在,那么说明文件已经存在,肯定不能重命名,也会报一个 DUPLICATE 的错误。如果 fn3 为空,那么就判断 fn2 文件是不是存在,如果存在那也是不能重命名的。

接下来,我们就可以将 fn2 重命名成 fn3, 然后将 fn1 重命名为 fn2,

如果 fn1 重命名为 fn2 出错,则将 fn3 重名名为 fn2 ,即撤消之前的修改操作。

那如果 fn3 为空,直接将 fn1 重命名为 fn2 就可以了,

标签:rename,插件,fn3,fn2,text,PG14,源码,pg,file
From: https://www.cnblogs.com/zardfans/p/18062886

相关文章

  • python基于flask房产中介房屋供求系统django毕业设计项目lw附源码
    本设计要设计一个简单的网页,在研究的过程中具体有以下5个步骤:下面简要分析房产中介系统的业务:(1)注册、登录:注册普通账号登录。(2)用户个人信息修改:登录后可以修改用户的基本信息,也可以退出。(3)用户留言管理:用户填写留言的主题、联系人、电话、邮箱、留言内容。 (4)房屋......
  • django-crontab项目源码阅读
    文章同步首发个人公众号菩提老鹰,欢迎大家订阅一、知识点这边源码阅读分析,可以获得如下知识点1、django-crontab的原理2、django-crontab任务ID如何生产3、django-crontab使用限制很早之前写过关于django-crontab的文章,比如django任务管理之crontabDjango实现c......
  • 手把手的使用Toolkit插件在诗情画意中完成AI诗朗诵
    本文分享自华为云社区《【云驻共创】手把手的使用Toolkit插件在诗情画意中完成AI诗朗诵》,作者:红目香薰。云原生时代,开发者们的编程方式、编程习惯都发生了天翻地覆的变化,大家逐渐地习惯在云端构建自己的应用。作为新一代的开发者们,如何更快速了解云,学习云,使用云,更便捷、更智能......
  • 全面解析 qiankun 源码
    本文将针对微前端框架qiankun的源码进行深入解析,在源码讲解之前,我们先来了解一下什么是微前端。微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将单页面前端应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立开发、独立......
  • 【前端素材】推荐优质在线绿色有机果蔬商城网页Fulo平台模板(附源码)
    一、需求分析绿色新鲜有机果蔬商城是指一个专门销售绿色、有机、新鲜水果和蔬菜的在线平台,旨在为用户提供优质的、健康的食品购物体验。1、功能分析:绿色新鲜有机果蔬商城是指一个专门销售绿色、有机、新鲜水果和蔬菜的在线平台,旨在为用户提供优质的、健康的食品购物体验。下......
  • 基于微信小程序的场地预约系统设计与实现(源码+lw+部署文档+讲解等)
    文章目录前言项目运行截图技术框架后端采用SpringBoot框架前端框架Vue可行性分析系统测试系统测试的目的系统功能测试数据库表设计代码参考数据库脚本为什么选择我?获取源码前言......
  • 基于微信小程序的宠物寄养平台小程序设计与实现(源码+lw+部署文档+讲解等)
    文章目录前言项目运行截图技术框架后端采用SpringBoot框架前端框架Vue可行性分析系统测试系统测试的目的系统功能测试数据库表设计代码参考数据库脚本为什么选择我?获取源码前言......
  • 鸿蒙开发入门实战案例-菜谱列表(附源码)
    昨天分享了鸿蒙的一些基础组件和布局方式,今天直奔主题,做一个菜谱列表,先看效果:这是实际开发中非常常见的列表样式,对初学者来说可能看起来有一些复杂,没关系,我们先从最简单的列表开始,一步一步实现它。昨天说过List列表组件的基本使用方式:List(){ListItem(){T......
  • 【计算机毕业设计源码】基于OpenCV的人脸检测系统
    项目概况基于OpenCV的人脸检测系统可对人脸进行框线检测,利用OpenCV的检测算法对单个或多个人脸实现框线定位。运行环境基于OpenCV的人脸检测系统运行环境如下:Python:≥3.5OpenCV:≥4.0IDE工具:VisualStudioCode技术栈:Python+OpenCV+PyQt5主要功能基于Ope......
  • 【MATLAB源码-第140期】基于matlab的深度学习的两用户NOMA-OFDM系统信道估计仿真,对比L
    操作环境:MATLAB2022a1、算法描述深度学习技术在无线通信领域的应用越来越广泛,特别是在非正交多址接入(NOMA)和正交频分复用(OFDM)系统中,深度学习技术被用来提高信道估计的性能和效率。信道估计是无线通信系统中的关键技术之一,它直接影响着系统的通信质量和可靠性。本文将详细介......