# centos7/postgresql(安装pl/python3扩展插件, 编写pl/python3方法)


## 安装python3

    1. 安装相关包: 
        yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make
        yum install libffi-devel -y
        cd /usr/bin
    
    2. 备份旧python命令(软连接): 
        mv python python.bak
        cd
    
    3. 下载压缩包: wget https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz
    解压: tar -xvJf Python-3.7.3.tar.xz
    
    4. 编译安装:./configure --enable-shared --prefix=/usr/local/python3 --enable-optimizations LDFLAGS="-Wl,--rpath=/usr/local/python3/lib"
        或编译安装(非linux版本, 此处不选用): ./configure --enable-shared --prefix=/usr/local  LDFLAGS="-R/usr/local/lib"
    make && make install
    cd /usr/bin
    制作软连接: ln -s /usr/local/python3/bin/python3 /usr/bin/python
    
    5. 检查版本: python -V
    因为yum使用python2, 所以修改yum使用python版本为2:
    vi /usr/bin/yum
    把#! /usr/bin/python修改为#! /usr/bin/python2
    同理 vi /usr/libexec/urlgrabber-ext-down 文件里面的#! /usr/bin/python 也要修改为#! /usr/bin/python2
    
    这样python3版本就安装完成；同时python2也存在
    python -V   版本3 
    python2 -V 版本2
    
    
## 编译安装postgresql(Centos7)

    1. 编译环境和下载安装包
        更新yum: yum update
        安装wget: yum install wget
        下载源码: wget https://ftp.postgresql.org/pub/source/v11.3/postgresql-11.3.tar.gz
        解压: tar zxvf postgresql-11.3.tar.gz
        安装编译需要的命令库: yum install gcc   yum install readline-devel    yum install zlib-devel
       
    2. 编译安装
        ./configure --with-python
        make (确保执行完最后一行出现All of PostgreSQL successfully made. Ready to install.)
        make install (最后一行出现PostgreSQL installation complete.为正常安装完成)
      
    3. 创建用户并授权
        useradd postgres
        chown -R postgres:postgres /usr/local/pgsql
        
        
    4. 配置环境变量
        切换到用户: su - postgres
        打开.bash_profile: vi ~/.bash_profile
        
![image](./img/plpython3_001.png)
        
        修改为如下:
            PGHOME=/usr/local/pgsql
            export PGHOME
            PGDATA=/usr/local/pgsql/data
            export PGDATA
             
            PATH=$PATH:$HOME/.local/bin:$HOME/bin:$PGHOME/bin
            export PATH
            
        修改完执行: source ~/.bash_profile
        
    5. 初始化数据库
        执行: initdb(初始化完毕后有提示开启服务的命令)
        开启数据库服务: pg_ctl -D /usr/local/pgsql/data -l logfile start     (关闭 stop/重启restart)
        查看版本: psql -V
        进入控制台: psql
        进入控制台后修改密码 \password postgres
        
    6. 配置连接规则
        在/usr/local/pgsql/data下, 有两个配置文件需要修改:
        postgresql.conf文件中, 需要配置
        
            listen_addresses = '*'     # 监听规则, *为监听所有
            
        pg_hba.conf文件中, 配置访问规则
        最后面加入一行
        
            host   all    all    0.0.0.0/0   trust
            
        详细配置可参考: 
        (https://www.cnblogs.com/flying-tiger/p/5983588.html)
        官网: https://www.postgresql.org/docs/current/auth-pg-hba-conf.html
        注: 比如对于IPv4地址来说， 172.20.143.89/32指定单个主机的IP，172.20.143.0/24代表一个小的子网。
            对于IPv6地址来说，::1/128指定单个主机(这里是本机环回地址)，fe80::7a31:c1ff:0000:0000/96 指定一个IPv6的子网。
            0.0.0.0/0代表所有IPv4地址，::0/0代表所有IPv6地址。
        配置完毕之后, 需要重启数据库服务方可生效.
    
    7. 启用并使用pl/python(plpython3u), create function
        1). 使用数据库浏览工具(比如navicat, pgAdmin4)连接刚配置完成的数据库
        2). 执行: create language plpython3u;  即创建对于python3的支持
        3). 如果需要import的库不存在, 则可以在python3/bin目录下执行pip3命令安装需要的库
            (例如: python pip3 install matplotlib 或./pip3 install matplotlib, 下面例子需要用到, 
            安装一般在python3目录下的lib/python3.7/site-packages目录下, pip3 show matplotlib可查)
        4). pip3 install matplotlib -i   
        5). 可以创建一个数据库function, 判断一个点是否在一个由多个点依次顺时针组成的面内.
        
## 示例 (注意: 输入参数名不能有大写字母)
    
    CREATE OR REPLACE FUNCTION is_point_in_polygon(IN the_point jsonb, IN the_polygon jsonb) RETURNS boolean AS
    $$
    from matplotlib.path import Path
    import json
    
    
    points = []
    poly = []
    a_point = json.loads(the_point)
    a_polygon = json.loads(the_polygon)
    points.append(a_point["x"])
    points.append(a_point["y"])
    points = tuple(points)
    
    l = len(a_polygon)
    for i in range(l):
        ele = a_polygon[i]
        single_point = []
        single_point.append(ele["x"])
        single_point.append(ele["y"])
        poly.append(tuple(single_point))
    p = Path(poly)
    return p.contains_points([points])
    $$
    LANGUAGE 'plpython3u' VOLATILE;
    
    
    验证
    select is_point_in_polygon('{"x":1.2, "y":3}', '[{"x":1.1, "y":1.1},{"x":1.1, "y":4.1},{"x":4.1, "y":4.1},{"x":4.1, "y":1.1}]')
    
    select is_point_in_polygon('{"x":1.1, "y":3}', '[{"x":1.1, "y":1.1},{"x":1.1, "y":4.1},{"x":4.1, "y":4.1},{"x":4.1, "y":1.1}]')
    