首页 文章 精选 留言 我的

精选列表

搜索[作品],共1956篇文章
优秀的个人博客,低调大师

Qt 开源作品 | 小伙子,给你的 Linux 系统写个 Launcher 吧

今天给大家分享一下:如何用 Qt 实现一个 launcher (程序启动器)。 运行效果: github 链接: https://github.com/alamminsalo/qml-launcher 代码很少,C++ 部分大约 100行代码。 下面是实现过程。 1. 创建 QML 应用 在 Qt Creator 依次点击: -> File -> New File or Project -> Applications -> Qt Quick Application 然后一路点击 next 直到 finish 。 2. 解析配置文件 Linux 系统里安装过的应用, 都会在 /usr/share/applications 目录下有相应的配置文件, 用于说明如何启动该应用,如下: #ls-1X/usr/share/applications/ apport-gtk.desktop apturl.desktop arduino.desktop audacity.desktop bcompare.desktop ... 以 bcompare.desktop 为例: [DesktopEntry] Name=BeyondCompare Exec=bcompare Icon=bcompare ... 字段含义: Name 字段是应用的名称, Exec 字段是应用的启动命令, Icon 字段是应用的图标名称, 解析配置文件: //文件:main.cpp QVariantListapps() { QVariantListret; QDirIteratorit(DESKTOP_FILE_SYSTEM_DIR,...); while(it.hasNext()){ constautofilename=it.next(); QSettingsdesktopFile(filename,QSettings::IniFormat); //定位到[DesktopEntry] desktopFile.beginGroup(DESKTOP_ENTRY_STRING); //提取app信息 AppInfoapp; app.exec=desktopFile.value("Exec").toString().remove("\"").remove(QRegExp("%.")); app.icon=desktopFile.value("Icon").toString(); app.name=desktopFile.value("Name").toString(); //保存app信息 ret.append(QStringList{app.name,app.icon,app.exec}); } returnret; } intmain(intargc,char*argv[]) { [...] //将解析到的app信息传递给QML前端 engine.rootContext()->setContextProperty("apps",apps()); [...] } 核心就是遍历某个目录下的所有文件,解析配置文件的工作则由 QSettings 负责。 运行效果: //打印出所有的app启动信息 exec:"xpad" icon:"xpad" name:"Xpad" [...] 3. 实现整体布局 我们通过 SwipeView 来实现滑动翻页的功能,参考我之前的文章: 《Qt 官方示例 | 这几个 QML 版的 HelloWorld 你学会了吗?》 至于单独一页的布局,我们可以使用 Repeater 这个控件。 Repeater 可以帮我们生成重复的内容,这里我们规定一页最多显示 24 个 app。 通过 SwipeView + Repeater 实现布局: //文件:main.qml SwipeView{ [...] propertyintselectedIndex:0 Repeater{ id:pageRepeater model:appPages.length Item{ propertyvarpage:appPages[index] Grid{ columns:6 Repeater{ model:page.length Image{ source:"qrc:/images/qtlogo.png" } } } } } } 第一个 Repeater 用于实现生成所有的页面, 第二个 Repeater 用于生成页面里的所有 APP 的图标,这里我们先用 Qt 的 logo 来代替真实的 APP 图标。 运行效果: 这时候已经支持左右滑动了,但是还没填入 APP 信息。 4. 支持显示应用图标 在 main() 里,我们设置了一个名为 apps 的属性,它包含了所有 APP 的信息: engine.rootContext()->setContextProperty("apps",apps()); 我们需要在前端界面中使用 APP 的图标替换掉 Qt logo。 显示 APP 图标: //文件:main.qml Grid{ [...] Repeater{ model:page!==undefined?page.length:0 Column{ Image{ propertyvarapp:page[index] //APP图标 source:"image://icons/"+app[1] [...] } Label{ propertyvarapp:page[index] id:label //APP的名称 text:app[0] [...] } } } } 改动非常少。 运行效果: 这时仅支持显示图标,但是仍不支持鼠标选中。 5. 支持选中应用 选中应用需要添加对鼠标 hover 事件的处理。 当鼠标移动到某个图标上时,Qt 会捕获到鼠标 hover 事件,并传递给当前焦点所在的控件上。 我们将 APP 的界面代码抽取出来,单独放在 AppEntry.qml,使其成为一个独立的控件, 然后再在其中添加对鼠标 hover 事件的处理。 图标控件:AppEntry.qml ///文件:AppEntry.qml Pane{ id:root propertyvarapp [...] //当鼠标移动到该图标时,发送信号hovered() signalhovered() MouseArea{ [...] onHoveredChanged:{ if(hovered){ root.hovered() } } } Column{ anchors.fill:parent Image{ source:"image://icons/"+app[1] [...] } Label{ [...] } } } 在 main.qml 中接受到 AppEntry 控件的 hovered 信号时, 需改变其背景色以提示用户已选中图标。 //文件:main.qml Repeater{ model:page.length AppEntry{ app:page[index] [...] //selected改变时,背景色会变化 selected:swipeView.selectedIndex===index onHovered:{ swipeView.select(index) } [...] } } 运行效果: 这是已经能显示选中状态了,但是仍无法启动应用。 6. 支持启动应用 在 Qt 里,可以使用 QProcess 来创建进程。 这里我们创建一个 QProcess 的子类用于运行 APP。 QProcess 的子类: //文件:process.cpp voidProcess::start(constQString&program,constQVariantList&arguments) { [...] QProcess::startDetached(program); } //文件:process.h classProcess:publicQProcess { Q_OBJECT public: Process(QObject*parent=nullptr); Q_INVOKABLEvoidstart(constQString&program,constQVariantList&arguments={}); }; //文件:main.cpp intmain(intargc,char*argv[]) { //将Process的实例传递给前端 engine.rootContext()->setContextProperty("proc",newProcess(&engine)); } 前端处理点击事件: //文件:AppEntry.qml signalclicked() MouseArea{ [...] onClicked:{ root.clicked() } } 当用户点击图标时,AppEntry 控件会发出 clicked() 信号。 //文件:main.qml AppEntry{ app:page[index] [...] //主窗口启动APP onClicked:{ exec(app[2]) } [...] } functionexec(program){ console.debug("Exec:"+program) proc.start(program) Qt.quit(); } 最后调用到 Process::start(),启动 APP。 运行效果: 怎么样,你们学会了吗? —— The End —— 推荐阅读: 专辑 | Linux 驱动开发 专辑 | Linux 系统编程 专辑 | 每天一点 C 专辑 | Qt 入门 想进交流群? 后台回复【加群】,我拉你进群。

优秀的个人博客,低调大师

Chameleon跨端框架——壹个理想主义团队的开源作品

文章较长,信息量很大,请耐心阅读,必然有收获。下面正文开始~ 背景 解决方案 原理 久经考验 生产应用举例 易用性好 多态协议 学习成本低 渐进式接入 业内对比 后期规划 理想主义 历经近20个月打磨,滴滴跨端方案chameleon终于开源了https://github.com/didi/chameleon, 真正专注于一套代码运行多端。 背景 微信月活10亿月活、支付宝4亿月活、百度3.3亿月活;2018 Q3中国Android手机占智能手机市场超过80%;无论BAT还是Android快应用都是中国互联网用户的真正用户入口,作为小型互联网公司都希望能搭上小程序的风口,从而蹭一波流量。 计算机技术历史发展告诉我们,每一种新技术出现都会经历"各自为政"的阶段,小程序技术也不例外。微信小程序作为首创者,虽然其他小程序都在技术实现原理、接口设计刻意模仿,但是作为一线开发者面对同样的应用实现往往需要重复开发、测试,从前1单位的工作量变成了N单位的工作量。 滴滴的研发工程师是其中最显著的"受害者"之一,滴滴出行在微信钱包、支付宝、Android快应用都有相关入口,用户流量占比不低。 各类原生跨端框架并驾齐驱: 从Facebook在2013年开源react,这个项目本身越滚越大。从最早的WebUI引擎衍生的ReactNative项目,目标更是宏伟。 Vue.js于2014年左右发布,逆流而上占据了大量用户群体,2016年阿里巴巴也基于vue发布了weex项目,可以用vue编写Native APP。 Google在2018年末正式发布了面向未来的跨Andoid、IOS端Flutter1.0.0,作为面向未来的跨端框架,前景一片光明。 解决方案 虽然不同各端框架环境千变万化,无论各类小程序、Weex、React-Native、Flutter、快应用,它们万变不离其宗的是MVVM架构设计思想。Chameleon希望既能用一套代码完成所有端需求,将相同的业务逻辑完成收敛到同一层系统里面,又不会因为项目的抽象一致导致可维护性变差。 让MVVM跨端环境大统一:以各个跨端技术(Wee x、React-Native、WebView浏览器、Flutter)和产品业务(微信小程序、快应用、支付宝小程序、百度智能小程序、今日头条小程序、其他各类小程序)的共同技术特点——MVVM架构设计, 以统一MVVM跨端架构平台为目标的程序语言框架Chameleon(任意使用MVVM架构设计的终端,都能以Chameleon开发并运行)。 View: ChameleonSDK包括各类小程序、web端、客户端(React-Native、Weex、Flutter),目前支持微信小程序、Web、Weex三类,后续支持更多MVVM为标准的端。 View Model: CML(Chameleon MarkupLanguage)是框架设计的一套标签语言,结合基础组件、事件系统、数据绑定,可以构建出页面的结构。同时为了降低学习成本支持类VueTemplate。 原理 久经考验 2017年时微信小程序发布,滴滴作为白名单用户首先开始尝试接入。这时候我们专门成立了一个1、2人的小项目组,完成一个名为MPV的项目,一期目标是“不影响用户发挥,不依赖框架方的原则性实现一套代码运行web和微信小程序”。MPV研发完成后,在多个项目实践中,确实完成了超过90%代码重用,总体上开发效率和测试效率都有了明显提升,同时暴露出更多问题: 可维护性问题,没有隔离公用代码和各端差异代码。 方向选择错误,MPV使用了小程序语法标准(小程序的生命周期、API接口等),导致用户使用上无法清晰理解使用规范。 各端周边小型差异点太多。 模板DSL语法不规范。 两端界面效果不一致。 多端调试成本高。 工程化建设落后。 不能直接使用各端已有生态组件,即缺乏标准规范接入某个端已有开源组件。 2018年4月我们把跨端项目规模进一步扩大,跨N端的解决方案命名为Chameleon/kmiln/,简写CML,中文名卡梅龙;中文意思变色龙,意味着就像变 色龙一样能适应不同环境的跨端整体解决方案。 Chameleon在MPV的实践积累下,不仅解决了遇到的各种问题,后续的规划更加明确,目标真正专注于让一套代码运行多端,提供标准的MVVM模式统一各类终端。 经过一年数十位前端开发人员在上百页面中的实践经验积累,于近日正式开源:https://github.com/didi/chameleon。 生产应用举例 易用性好 一套代码运行多端理念,被人挑战最多的如何保证易用性。 开发快,整体开发流程要高效。 简洁性,各端开发定制化空间大,且公用代码不会混杂某端代码。 性能好,不能增加产出文件包大小。 一致性,多端实现效果一致。 多态协议 多端合并后各端差异化实现在所难免,一开始是差异化代码和业务逻辑混杂在一起。这就尴尬了,如果你觉得以上不复杂,假设有4、5个端呢,业务逻辑掺杂跨端逻辑,产品逻辑别打断,可读性差,需求变更,牵一发动全身,每个端都要测试,跨端代码效率变得适得其反。 下图各端差异化代码也和逻辑混合在一起 多态协议设计的灵感来自于Apache Thrift - 可伸缩的跨语言服务开发框架,本质上跨端也属于跨语言。 它能让Chameleon开发者快速接入各个客户端底层功能或者差异化业务实现,避免可读性差、可维护性差的问题。 多态协议通过定义标准接口(interface),各端模块各自独立实现,编译时和运行时对实现的接口输入输出做检查。 主要2个目标: 保障多端可维护性 编译时拆分多端代码 当用户按照标准规范扩展个别产品效果多端不一致或特定底层能力多端不一致的的功能时,多态协议可以有效隔离公用代码和各端差异代码,保证”河水不犯井水“。 举例:当你像开发一个图表功能组件时,可能用到 echarts : 在项目中分别按照web版本 npm install echarts 和微信版本下载相关文件 然后定义一个多态组件 charts 在 charts/charts.interface 定义该组件的输入和输出 分别在 charts/charts.wx.cml 和 charts/charts.web.cml 里面调用微信版本(可使用微信小程序组件文件夹)和web版本(可调用.vue后缀文件) 最后就能在项目中使用该组件 产出包里面只包含该组件其中一端的代码;因输入输出的限制,该组件调用上完全一致,不用根据某端做特殊逻辑处理。你可以将该echart多态组件单独放置在一个仓库里面单独维护并发布;其他人无需关系内部细节,直接npm install echart即可使用。 学习成本低 VM层的CML语法是关联视图层和逻辑层的抽象DSL,其有学习成本问题是被热心很多帮助我们的同学提的最多建议,本身其CML学习成本已经非常低,无非是数据双向绑定、事件绑定、组件树、条件语句、循环遍历等等。一开始我们是拒绝的,后来综合考虑之下,还是妥协支持了类vue语法,让开发者更快上手CML。 渐进式接入 很多人已经开发小程序了,又不愿意大多阔斧重新改造,也希望使用CML?当然可以,两种方式使用CML: 业内对比 业内其他框架和我们的目标不一样,我们是希望真正一套代码运行多端,而其他框架无非是“某个小程序语法增强”或者“推广某个框架写小程序 ”,但却是有重合点,列举一下功能对比: 后期规划 理想主义 我们忍受不了自己的时间浪费在重复劳动上。 要么不做要做就到极致,一套代码运行多端本来就是理想主义,这条路很艰苦,我们却偏执的坚信一定要尽最大努力做出来,作为一个不那么自 信的人,不做到好用是不敢发布出来的。 CML框架各个细节都要做到极致,我们不能容忍有设计上的缺陷,所以常常CML周会上团队成员讨论6个小时直到深夜。 快速开始:https://cmljs.org/doc/quick_start/quick_start.html 常见问题: https://cmljs.org/doc/framework/faq.html 欢迎加入贡献代码:didi/chameleon

优秀的个人博客,低调大师

【参赛作品11】过程化SQL以及openGauss存储过程、函数、触发器

一、 过程化SQL 基本的SQL是高度非过程化的语言。嵌入式SQL将SQL语句嵌入程序设计语言,借助高级语言的控制功能实现过程化。过程化SQL是对SQL的扩展,使其增加了过程化语句功能。 简单来说,从标准SQL语句到嵌入式SQL再到过程化SQL,就是使SQL功能不断增强的过程。标准SQL语句相当于是可以操纵数据库的一些“武器”,嵌入式SQL相当于给程序设计语言(如java,C语言等)装备了这些“武器”,而过程化SQL相当于给这些“武器”予以血肉,通过自身带有的流程控制语句操纵数据库。 过程化SQL程序的基本结构是块。所有的过程化SQL程序都是由块组成的。这些块之间可以相互嵌套,每个块完成一个逻辑操作。学会用过程化SQL书写存储过程和触发器就会像写C语言代码一样随心所欲。 1、变量和常量的定义 (1)变量定义 变量名 数据类型 [[NOT NULL] :=初值表达式] 或 变量名 数据类型 [[NOT NULL] 初值表达式] (2)常量定义 常量名 数据类型 CONSTANT:=常量表达式 【注】常量必须要给一个值,并且该值在存在期间或常量的作用域内不能改变。如果试图修改它,过程化SQL将返回一个异常。 (3)赋值语句 变量名 :=表达式 2、选择控制语句 (1)IF语句 IF condition THEN Sequence_of_statements; /*条件为真时才执行该条语句*/ END IF /*条件为假或NULL时什么也不做,控制转移至下一个语句*/ (2)IF-ELSE语句 IF condition THEN Sequence_of_statements1; /*条件为真时语句序列才被执行*/ ELSE Sequence_of_statements2; /*条件为假或NULL时才被执行*/ END IF (3)嵌套的IF语句 在THEN和ELSE子句中还可以包含IF语句,IF语句可以嵌套,如: IF condition THEN IF condition THEN Sequence_of_statements1; END IF ELSE IF condition THEN Sequence_of_statements2; ELSE Sequence_of_statements3; END IF END IF 3、循环控制语句 (1)LOOP循环语句 LOOP Sequence_of_statements; /*循环体,一组过程化SQL语句*/ END LOOP; 该循环必须要结合EXIT使用,否则将陷入死循环。 举例: CREATE OR REPLACE PROCEDURE proc_loop(IN i integer, OUT count integer) IS BEGIN count:=0; LOOP IF count > i THEN raise info 'count is %. ', count; EXIT; ELSE count:=count+1; END IF; END LOOP; END; / CALL proc_loop(10,5); (2)WHERE-LOOP循环语句 WHERE condition LOOP Sequence_of_statements; /*条件为真时执行循环体内的语句序列*/ END LOOP; 每次执行循环体语句之前首先对条件进行求值,如果条件为真则执行循环体内的语句序列,如果条件为假则跳过循环并把控制传递给下一个语句。 举例: CREATE OR REPLACE PROCEDURE proc_while_loop(IN maxval integer) IS DECLARE i int :=1; BEGIN WHILE i < maxval LOOP INSERT INTO integertable VALUES(i); i:=i+1; END LOOP; END; / (3)FOR-LOOP循环语句 FOR count IN [REVERSE] bound1...bound2 LOOP Sequence_of_statements; END LOOP; 将count设置为循环的下界bound1,检查它是否小于上界bound2。当指定REVERSE时则将count设置为循环的上界bound2,检查count是否大于下界bound1。如果越界则执行跳出循环,否则执行循环体,然后按照步长(+1或-1)更新count的值,重新判断条件。 有点像python中的for…in range(i,j)循环。 二、openGauss下的存储过程、函数、触发器书写 过程化SQL块主要有命名块和匿名块。匿名块每次执行时都要进行编译,它不能被存储到数据库中,也不能在其他过程化SQL块中调用。过程和函数是命名块,他们被编译后保存在数据库中,称为持久性存储模块(PSM),可以 被反复调用,运行速度较快。 1、存储过程 存储过程是由过程化SQL语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,因此称它为存储过程,使用时只要调用即可。 (1)存储过程的优点 1)由于存储过程不像解释执行的SQL语句那样在提出操作请求时才进行语法分析和优化工作,因而运行效率高,它提供了在服务器端快速执行SQL语句的有效途径。 2)存储过程降低了客户机和服务器之间的通信量。客户机上的应用程序只要通过网络向服务器发出调用存储过程的名字和参数,就可以让关系数据库管理系统执行其中的多条SQL语句并进行数据处理,只有最终的处理结果才返回客户端。 3)方便实施企业规则。可以把企业规则的运算程序写成存储过程放入数据库服务器中,由关系数据库管理系统管理,既有利于集中控制,又能够方便地进行维护。当企业规则发生变化时只要修改存储过程即可,无需修改其他应用程序。 (2)创建存储过程 CREATE OR REPLACE PROCEDURE 存储过程名 ( [参数1模式 参数1名字 参数1类型] ,..) IS BEGIN <标准SQL或过程化SQL> END; / (不要忘了最后一行的斜杠) 调用存储过程: CALL 存储过程名(参数1,..); 举例: CREATE OR REPLACE PROCEDURE update_num ( IN daily_id CHAR(4) ) IS BEGIN UPDATE 代理商 SET 代理客户数 = (SELECT count(*) FROM 客户 WHERE 代理商编号=daily_id GROUP BY 代理商编号 ) WHERE 代理商编号=daily_id; END; / CALL update_num('01'); (3)修改存储过程 ALTER PROCEDURE 过程名1 RENAME TO 过程名2;(重新命名一个存储过程) ALTER PROCEDURE 过程名 COMPILEL;(重新编译一个存储过程) (4)删除存储过程 DROP PROCEDURE 过程名(); 2、函数以及触发器 函数必须指定返回的类型。openGauss中的触发器要先定义一个触发器函数,再利用这个函数,定义触发器。 (1)创建函数及触发器 创建触发器函数: CREATE OR REPLACE FUNCTION 触发器名称() RETURNS TRIGGER AS $$ DECLARE BEGIN <标准SQL或过程化SQL> RETURN <NEW或OLD>; END; $$ LANGUAGE PLPGSQL; 创建触发器,其中调用上面创建的触发器函数: CREATE TRIGGER 触发器名称 <BEFORE|AFTER|INSTEAD OF> <INSERT|UPDATE|DELETE> ON 表名 <FOR EACH ROW | FOR EACH STATEMENT> EXECUTE PROCEDURE 触发器函数名(); BEFORE:触发器函数是在触发事件发生前执行。 AFTER:触发器函数是在触发事件发生后执行,约束触发器只能指定为AFTER。 INSTEAD OF:触发器函数直接替代触发事件。 FOR EACH ROW:指该触发器是受触发事件影响的每一行触发一次。 FOR EACH STATEMENT:指该触发器是每个SQL语句只触发一次。 (未指定时默认值为FOR EACH STATEMENT。约束触发器只能指定为FOR EACH ROW ) 举例: CREATE OR REPLACE FUNCTION tri_insert_订货项目_func() RETURNS TRIGGER AS $$ DECLARE BEGIN UPDATE 产品 SET 产品订单数=产品订单数+1,库存量=库存量-NEW.订购数量 WHERE 产品编号=NEW.产品编号; RETURN NEW; END; $$ LANGUAGE PLPGSQL; CREATE TRIGGER after_insert_订货项目 AFTER insert ON 订货项目 FOR EACH ROW EXECUTE PROCEDURE tri_insert_订货项目_func(); (2)善于用过程化SQL书写存储过程和函数 (往赛程表中插入一条比赛信息,若比分1大于比分2,则球队1的总场数、总胜场+1,球队2的总场数+1…) C REATE OR REPLACE FUNCTION insert_func2() RETURNS TRIGGER AS $$ DECLARE BEGIN if new.比分1>new.比分2 then update 球队 set 总场数=总场数+1,总胜场=总胜场+1 where 球队名称=new.球队1名称; update 球队 set 总场数=总场数+1 where 球队名称=new.球队2名称; else if new.比分1<new.比分2 then update 球队 set 总场数=总场数+1 where 球队名称=new.球队1名称; update 球队 set 总场数=总场数+1,总胜场=总胜场+1 where 球队名称=new.球队2名称; else update 球队 set 总场数=总场数+1 where 球队名称=new.球队1名称; update 球队 set 总场数=总场数+1 where 球队名称=new.球队2名称; end if; end if; RETURN NEW; END; $$ LANGUAGE PLPGSQL; CREATE TRIGGER after_insert2 AFTER INSERT ON 赛程 FOR EACH ROW EXECUTE PROCEDURE insert_func2() ; (如果比赛类型为小组赛,且比分1大于比分2,那么意味着球队1胜,球队2负,然后更新球队有关属性信息…) CREATE OR REPLACE FUNCTION insert_func() RETURNS TRIGGER AS $$ DECLARE BEGIN if new.比赛类型='小组赛' then if new.比分1>new.比分2 then update 球队 set 小组赛胜场=小组赛胜场+1,小组赛进球数=小组赛进球数+new.比分1,小组赛失球数=小组赛失球数+new.比分2,小组赛积分=小组赛积分+3 where 球队名称=new.球队1名称; update 球队 set 小组赛负场=小组赛负场+1,小组赛进球数=小组赛进球数+new.比分2,小组赛失球数=小组赛失球数+new.比分1 where 球队名称=new.球队2名称; else if new.比分1<new.比分2 then update 球队 set 小组赛负场=小组赛负场+1,小组赛进球数=小组赛进球数+new.比分1,小组赛失球数=小组赛失球数+new.比分2 where 球队名称=new.球队1名称; update 球队 set 小组赛胜场=小组赛胜场+1,小组赛进球数=小组赛进球数+new.比分2,小组赛失球数=小组赛失球数+new.比分1,小组赛积分=小组赛积分+3 where 球队名称=new.球队2名称; else update 球队 set 小组赛平场=小组赛平场+1,小组赛进球数=小组赛进球数+new.比分1,小组赛失球数=小组赛失球数+new.比分2,小组赛积分=小组赛积分+1 where 球队名称=new.球队1名称; update 球队 set 小组赛平场=小组赛平场+1,小组赛进球数=小组赛进球数+new.比分2,小组赛失球数=小组赛失球数+new.比分1,小组赛积分=小组赛积分+1 where 球队名称=new.球队2名称; end if; end if; end if; RETURN NEW; END; $$ LANGUAGE PLPGSQL; CREATE TRIGGER after_insert AFTER INSERT ON 赛程 FOR EACH ROW EXECUTE PROCEDURE insert_func() ; (3)修改触发器 ALTER TRIGGER trigger_name ON table_name RENAME TO new_name; (4)删除触发器 DROP TRIGGER [ IF EXISTS ] trigger_name ON table_name [ CASCADE | RESTRICT ]; 1)删除触发器时,如果不指定触发器所在的表,则会报错 2)在openGauss中删除触发器时,先删触发器本身,再删触发器中所定义的函数,否则会报错 3)IF EXISTS:如果指定的触发器不存在,则发出一个notice而不是抛出一个错误。 Gauss松鼠会是汇集数据库爱好者和关注者的大本营, 大家共同学习、探索、分享数据库前沿知识和技术, 互助解决问题,共建数据库技术交流圈。 openGauss官网

优秀的个人博客,低调大师

我的第一个MVC作品—燕赵宽频点播系统源码

代朋友(hevod.com)在园子里转发一个原创的视频点播系统,采用简单三层开发,希望得到大家的支持与鼓励! 其中有一些纰漏支持,还望各位指正! 燕赵宽频视频点播平台V1.0 开发环境:VS2005+Access hevod视频点播系统是一套采用Asp.net开发开源的视频在线播放系统,系统采用三层架构开发,数据库采用Access,适合于中小型网站应用,源码仅供个人学习参考,不得用于任何商业用途。 1、公用部分采用了用户控件进行调用 2、用户分权限管理,后台随时记录用户登录日志 网站前台页面和后台页面详见截图 前台页面均是采用div+css构建(目前只在IE6.0下调试,在其他浏览器版本下可能会产生错乱哦),第一次用div+css哦,不妥及兼容不当之处还请各位用户见谅。 由于本人不会设计页面,所以前后台页面均是改自互联网 演示及源码下载地址:http://www.hevod.com/default.aspx 本文转自 liudao 博客园博客,原文链接:http://www.cnblogs.com/liudao/archive/2008/01/24/1051060.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Qt编写的项目作品10-RTSP播放器+视频监控(android版本)

一、功能特点 多线程实时播放rtsp视频流。 支持X86和嵌入式linux。 多线程显示图像,不卡主界面。 自动重连网络摄像头。 可设置边框大小即偏移量和边框颜色。 可设置是否绘制OSD标签即标签文本或图片和标签位置。 可设置两种OSD位置和风格。 可设置是否保存到文件以及文件名。 可设置间隔时间段保存文件到指定目录。 可播放本地视频文件,支持设置帧率。 支持h265视频流+rtmp等常见视频流。 可暂停播放和继续播放。 支持定时存储文件,包括音频和视频。 支持sdl播放音频。 支持外部拖曳文件+拖曳节点数据进行播放。 自定义顶部悬浮条,发送单击信号通知,可设置是否启用。 二、效果图 三、体验地址 体验地址:https://pan.baidu.com/s/1bbL2ZughZAgfIGrexyN-9g 提取码:zkeh 名称:bin_video_android.zip 国内站点:https://gitee.com/feiyangqingyun 国际站点:https://github.com/feiyangqingyun 个人主页:https://blog.csdn.net/feiyangqingyun 知乎主页:https://www.zhihu.com/people/feiyangqingyun/ 备注:如果网盘下载不到可以去开源主页下载

优秀的个人博客,低调大师

【参赛作品7】PostgreSQL/openGauss数据库易犯的十大错误

总结十点PostgreSQL/openGauss数据库中容易犯的错误。 1.同时设置日志行前缀和csvlog格式 比较常见大家同时配置下面这两个参数 log_line_prefix = '%m %u %d %p' log_destination='csvlog' %m是带毫秒的时间戳 %u是用户名 %d是数据库名 %p是进程ID 然后当我们配置为csvlog日志时,日志行的内容项是固定的,所以当我们需要配置日志前缀,精简日志行的内容项时,log_destination不能配置为csvlog。下面是正确的配置: log_destination='stderr' log_line_prefix = '%m %u %d %p' 2.不符合预期的日志轮换策略 日志轮换策略可以通过log_rotation_size参数按日志文件大小控制或者通过log_rotation_age参数按时间控制,但下面这四个参数需要合理组合使用。 log_filename log_truncate_on_rotation log_rotation_age log_rotation_size 方案一:每天生成一个新的日志文件 log_filename='postgresql-%Y-%m-%d.log' log_truncate_on_rotation=off log_rotation_age=1d log_rotation_size=0 方案二:写满固定大小(如10MB),则进行切换 log_filename='postgresql-%Y-%m-%d_%H%M%S.log' log_truncate_on_rotation=off log_rotation_age=0 log_rotation_size=10MB 这种方案我们一般是为了根据时间去查看日志,文件名根据日志量可以设置到时分秒,但这里设置log_rotation_size并不能严格控制固定大小。 方案三:保留固定天数的日志并循环覆盖,例如固定一周或者固定一个月 log_filename='postgresql-%u.log' log_truncate_on_rotation=on log_rotation_age=1d log_rotation_size=0 log_filename常见的通配符变量 %u是星期的数字表示,范围是[1,7],1代表星期一 %w也是星期的数字表示,范围是[0,6],0代表星期天 %d是月份中的天数表示,范围是[01,31] 生产环境第三种方案更合适一些。 3.同步复制表的序列 看看下面这个例子,我们创建test表使用serial自增序列类型,系统帮我们生成了test_id_seq序列。 postgres=# create table test(id serial primary key,name varchar unique); CREATE TABLE postgres=# \d test Table "public.test" Column | Type | Collation | Nullable | Default --------+-------------------+-----------+----------+---------------------------------- id | integer | | not null | nextval('test_id_seq'::regclass) name | character varying | | | Indexes: "test_pkey" PRIMARY KEY, btree (id) "test_name_key" UNIQUE CONSTRAINT, btree (name) 当我们复制t_test表时,test表的序列引用也同时复制过来了,可以使用虚拟生成列来解决这个问题。 postgres=# create table t_test(like test including all); CREATE TABLE postgres=# \d t_test Table "public.t_test" Column | Type | Collation | Nullable | Default --------+-------------------+-----------+----------+---------------------------------- id | integer | | not null | nextval('test_id_seq'::regclass) name | character varying | | | Indexes: "t_test_pkey" PRIMARY KEY, btree (id) "t_test_name_key" UNIQUE CONSTRAINT, btree (name) openGauss对PG的这个问题做了修复,下面是openGauss复制t_test时,序列按表名做了区分。 omm=# \d t_test Table "public.t_test" Column | Type | Modifiers --------+-------------------+----------------------------------------------------- id | integer | not null default nextval('t_test_id_seq'::regclass) name | character varying | Indexes: "t_test_pkey" PRIMARY KEY, btree (id) TABLESPACE pg_default "t_test_name_key" UNIQUE CONSTRAINT, btree (name) TABLESPACE pg_default 4.跳变的序列值 创建序列seq1,设置cache为10,session A获取下一个值为1. postgres=# create sequence seq1 cache 10; CREATE SEQUENCE postgres=# select nextval('seq1'); nextval --------- 1 (1 row) session B查询获取下一个值为11 postgres=# select nextval('seq1'); nextval --------- 11 (1 row) 序列值插入为了保证连续性,要设置cache为1。 5.从任意库查询pg_stat_statements模块统计信息 pg_stat_statements模块用来跟踪SQL语句的执行统计信息,我们如果把该模块安装到postgres数据库,就只能连到postgres数据库进行查询,除非其它数据库也安装了该模块,否则会提示报错找不到。 无论任何操作,都需要连接到一个数据库,即使我们只想创建一个全局的数据库用户,所以选对数据库特别重要。 6.truncate操作理解为DML语句 log_statement参数控制日志记录级别,有4个选项:none、ddl、mod、all。开启ddl,它会记录 create、alter和drop相关的语句,但不记录truncate。 truncate在Oracle中属于DDL语句,在PostgreSQL中属于DML语句。因此,当我们使用DDL日志记录语句时,无法记录到Truncate。 7.认为数据库的owner可以管理其下所有对象 数据库、模式、表的都有自己的owner,他们都属于实例中的对象,数据库owner只是具有数据库这个对象的CTc权限。数据库的默认权限为: 允许public角色连接,即允许任何人连接。 不允许除了超级用户和owner之外的任何人在数据库中创建schema。 会自动创建名为public的schema,这个schema的所有权限已经赋予给public角色,即允许任何人在里面创建对象。 schema使用注意事项: schema的owner默认是该schema下的所有对象的owner,但是允许用户在别人的schema下创建对象,所以一个对象的owner和schema的owner可能不同,都有drop对象的权限。 8.认为public模式下的对象可以互相访问 public模式只是允许任何人在里面创建对象并管理自己的对象,并不能查看别人创建的对象。 9.创建索引时起名为表名称 单个数据库里,索引和表的名称不能重复,因为他们都属于relation。 postgres=# create index a on a(id); ERROR: relation "a" already exists 10.把walsender当作主库 通常我们从操作系统层查看主库有walsender,备库有walreceiver,并且walsender信息中可以看到备库的IP地址,可以初步判断主备状态正常。 但请注意有walsender或者数据库中能查到pg_stat_replication视图并不能断定是主库,仅在一主一备环境可以这样简单判断,下面的图可以看出,虽然有walsender,但它也是个备库。

优秀的个人博客,低调大师

Qt编写的项目作品24-人脸识别综合应用(在线+离线+嵌入式)

一、功能特点 支持的功能包括人脸识别、人脸比对、人脸搜索、活体检测等。 在线版还支持身份证、驾驶证、行驶证、银行卡等识别。 在线版的协议支持百度、旷视,离线版的支持百度,可定制。 除了支持X86架构,还支持嵌入式linux比如contex-A9、树莓派等。 每个功能的执行除了返回结果还返回执行用时时间。 多线程处理,通过type控制当前处理类型。 支持单张图片检索相似度最高的图片。 支持指定目录图片用来生成人脸特征值文件。 可设置等待处理图片队列中的数量。 每次执行都有成功或者失败的信号返回。 人脸搜索的返回结果包含了原图+最大相似度图+相似度等。 人脸比对同时支持两张图片和两个特征值比对。 相关功能自定义一套协议用于客户端和服务端,可以通过TCP通信进行交互。 自定义人脸识别协议非常适用于中心一台服务器,现场若干设备请求的场景。 每个模块全部是独立的一个类,代码整洁、注释完善。 自定义人脸识别协议功能: 离线使用,同时支持百度的离线包和嵌入式linux人脸识别静态库。 支持多个连接并发,自动排队处理,返回的时候带上唯一标识区分。 传入单张图片返回人脸区域。 传入单张图片返回人脸特征值。 传入单张图片或者多张图片返回是否是活体。 传入两张图片返回比对结果。 传入两个特征值返回比对结果。 传入单张图片添加人脸。 指定唯一标识符删除人脸。 传入单张照片返回相似度最大的人脸信息。 修改人脸服务的配置参数比如是否快速查找、人脸占比等。 二、效果图 三、体验地址 体验地址:https://pan.baidu.com/s/1bbL2ZughZAgfIGrexyN-9g 提取码:zkeh 名称:bin_video_face.zip 国内站点:https://gitee.com/feiyangqingyun 国际站点:https://github.com/feiyangqingyun 个人主页:https://blog.csdn.net/feiyangqingyun 知乎主页:https://www.zhihu.com/people/feiyangqingyun/ 备注:如果网盘下载不到可以去开源主页下载

优秀的个人博客,低调大师

语音写字板 v1.01 我的第二个Android作品

语音写字板 英文名:VoiceTextPad 这是一个用于快速录入中长篇幅文档的工具,你可以使用语音输入结合系统安装的输入法来完成输入,内置了撤销/前进功能以便于在语音识别错误时快速撤销重输,输入完成后可以通过复制、导出、分享功能方便地转到其他应用中使用。 软件支持安装到SD卡 截图 下载 http://cid-0612298d2255e149.office.live.com/self.aspx/.Public/%E8%BD%AF%E4%BB%B6/VoiceTextPad.apk 也可以通过下面的链接或二维码转向菜市场下载: market://search?q=pname:com.skyd.voicetextpad 目前该软件已登录官方菜市场、eoe优异市场、Hiapk安卓市场、机锋市场。

优秀的个人博客,低调大师

ACL前瞻:国内五篇作品入选杰出论文,华人影响力日渐显现|ACL 2017

ACL是自然语言处理和计算机语言学最顶尖的会议之一,被CCF(中国计算机学会)推荐为A类国际学术会议,涵盖领域包括语言分析、信息抽取、机器翻译与自动问答等。今年的ACL将于2017年7月30日至8月4日在加拿大温哥华举行。雷锋网(公众号:雷锋网)AI科技评论将赴前线带来一手报道,并对论文及大会概况进行梳理。 先上一组数字了解下今年ACL的投递情况: 根据统计,本届会议共收到1419篇论文,其中长文829篇、短文590篇,最终录用长文195篇(录用率23.5%)、短文149篇。 在被录用的长文论文中,有79篇论文的第一作者为华人,约占被录用长文总数的40%。根据jeffhuang所统计的消息,自1996年以来的ACL最佳论文及作者列表如下: 从列表的第一作者及所属机构中,我们不难发现,从2001年开始鲜少出现华人面孔,而一直到2008年,最

优秀的个人博客,低调大师

[阿里云良心作品]

首先你需要买一个阿里云服务器,买的时候可以选择操作系统(买完之后在控制台也可以更改操作系统) 购买阿里云服务器前,请先到阿里云官网 领取幸运券,然后再购买,除了价格上有很多优惠 我使用的是CentOS,买完服务器之后需要添加一个多语言环境,这个需要到云市场搜索“多语言环境”并购买,有免费的,有收费的,看你需要哪一种,我用的免费的。 然后进入控制台,找到云服务器ECS 进入云服务器ECS,点击实例,里面有你购买的服务器 点击更多,然后重置密码,重置密码后需要重启服务器,点击管理,右上角有重启选项,配置好之后返回,点击远程连接,这时他会给你一个管理终端密码,记住这个密码。 然后输入管理终端密码进入服务器。 进入时需要输入登陆账号(默认是root) 和密码(刚刚重置的密码)然后就连接成功。 接下来需要下载Xftp和Xshell,Xftp是用于文件传输,也就是将你本地的php网页传输到阿里云服务器上,Xshell是登录到阿里云服务器。 打开Xshell,新建会话取名字,我的名称是test,协议选SSH,主机是阿里云服务器的公网ip地址,在控制台的实例中可以看到。 然后输入用户名(root)和密码就可以用Xshell操作阿里云服务器了。之后如果你的多语言环境(上面有提到)配置好了,那么打开浏览器输入公网地址会有下面的页面出现(如果被拒绝请关闭阿里云服务器的防火墙,输入service iptables stop): 点击《CentOS Nginx PHP JAVA多语言镜像使用手册V1.6.pdf》,建议将手册看一看,里面有很多操作我就不一一说了。注意到有一个 phpMyAdmin ,这是阿里云服务器的数据库,点击进入可以用本地浏览器操作。phpMyAdmin的用户名和密码在使用手册里有,自己去看下。登陆后将你本地的数据库导入,你需要新建一个数据库(跟本地数据库相同),然后把从本地数据库导出的SQL文件导入到阿里云服务器上,数据库导入就成功了。 手册里有源码安装目录 将你需要部署的网站部署到网站根目录下,就可以访问你的网站了。具体将Xshell打开,确保你也下载了Xftp,点击新建文件 它会自动运行Xftp,左边是你本地的目录,右边是你的阿里云的目录,找到你的php文件,将php文件拖入右边网站根目录下,就可以访问网站了,注意是网站根目录不是root。 网站运行结果:

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册