first commit
This commit is contained in:
275
libraries/vendor/joomla/database/.drone.jsonnet
vendored
Normal file
275
libraries/vendor/joomla/database/.drone.jsonnet
vendored
Normal file
@ -0,0 +1,275 @@
|
||||
local volumes = [
|
||||
{
|
||||
name: 'composer-cache',
|
||||
path: '/tmp/composer-cache',
|
||||
},
|
||||
];
|
||||
|
||||
local hostvolumes = [
|
||||
{
|
||||
name: 'composer-cache',
|
||||
host: { path: '/tmp/composer-cache' },
|
||||
},
|
||||
];
|
||||
|
||||
local composer(phpversion, params) = {
|
||||
name: 'Composer',
|
||||
image: 'joomlaprojects/docker-images:php' + phpversion,
|
||||
volumes: volumes,
|
||||
commands: [
|
||||
'php -v',
|
||||
'sleep 20',
|
||||
'composer update ' + params,
|
||||
],
|
||||
};
|
||||
|
||||
local phpunit_common(phpversion) = {
|
||||
name: 'PHPUnit',
|
||||
image: 'joomlaprojects/docker-images:php' + phpversion,
|
||||
[if phpversion == '8.3' then 'failure']: 'ignore',
|
||||
commands: [
|
||||
'vendor/bin/phpunit --configuration phpunit.xml.dist --testdox',
|
||||
],
|
||||
};
|
||||
|
||||
local phpunit_mysql(phpversion, driver) = {
|
||||
name: 'PHPUnit',
|
||||
image: 'joomlaprojects/docker-images:php' + phpversion,
|
||||
[if phpversion == '8.3' then 'failure']: 'ignore',
|
||||
commands: [
|
||||
'php --ri ' + driver + ' || true',
|
||||
'sleep 20',
|
||||
'vendor/bin/phpunit --configuration phpunit.' + driver + '.xml.dist --testdox',
|
||||
],
|
||||
};
|
||||
|
||||
local phpunit(phpversion, driver) = {
|
||||
name: 'PHPUnit',
|
||||
image: 'joomlaprojects/docker-images:php' + phpversion,
|
||||
[if phpversion == '8.3' then 'failure']: 'ignore',
|
||||
commands: [
|
||||
'php --ri ' + driver + ' || true',
|
||||
'vendor/bin/phpunit --configuration phpunit.' + driver + '.xml.dist --testdox',
|
||||
],
|
||||
};
|
||||
|
||||
local phpunit_sqlsrv(phpversion) = {
|
||||
name: 'PHPUnit with MS SQL Server',
|
||||
image: 'joomlaprojects/docker-images:php' + phpversion,
|
||||
commands: [
|
||||
'apt-get update',
|
||||
'apt-get install -y software-properties-common lsb-release gnupg',
|
||||
'curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -',
|
||||
'echo "deb [arch=amd64,armhf,arm64] https://packages.microsoft.com/ubuntu/22.04/prod jammy main" >> /etc/apt/sources.list',
|
||||
'apt-get update',
|
||||
'ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev',
|
||||
'pecl install sqlsrv && docker-php-ext-enable sqlsrv',
|
||||
'pecl install pdo_sqlsrv && docker-php-ext-enable pdo_sqlsrv',
|
||||
'php --ri sqlsrv',
|
||||
'php --ri pdo_sqlsrv',
|
||||
'vendor/bin/phpunit --configuration phpunit.sqlsrv.xml.dist --testdox',
|
||||
],
|
||||
};
|
||||
|
||||
local pipeline_sqlite(phpversion, driver, params) = {
|
||||
kind: 'pipeline',
|
||||
name: 'PHP ' + phpversion + ' with SQLite (' + driver + ')',
|
||||
environment: { DB: driver },
|
||||
volumes: hostvolumes,
|
||||
steps: [
|
||||
composer(phpversion, params),
|
||||
phpunit(phpversion, driver),
|
||||
],
|
||||
};
|
||||
|
||||
local pipeline_mysql(phpversion, driver, dbversion, params) = {
|
||||
kind: 'pipeline',
|
||||
name: 'PHP ' + phpversion + ' with MySQL ' + dbversion + ' (' + driver + ')',
|
||||
environment: { DB: driver },
|
||||
volumes: hostvolumes,
|
||||
steps: [
|
||||
composer(phpversion, params),
|
||||
phpunit_mysql(phpversion, driver),
|
||||
],
|
||||
services: [
|
||||
{
|
||||
name: driver,
|
||||
image: 'bitnami/mysql:' + dbversion,
|
||||
environment: {
|
||||
ALLOW_EMPTY_PASSWORD: 'yes',
|
||||
MYSQL_DATABASE: 'joomla_ut',
|
||||
MYSQL_ROOT_PASSWORD: '',
|
||||
MYSQL_AUTHENTICATION_PLUGIN: 'mysql_native_password',
|
||||
},
|
||||
ports: [
|
||||
{
|
||||
container: 3306,
|
||||
host: 3306,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
local pipeline_mariadb(phpversion, driver, dbversion, params) = {
|
||||
kind: 'pipeline',
|
||||
name: 'PHP ' + phpversion + ' with MariaDB ' + dbversion + ' (' + driver + ')',
|
||||
environment: { DB: driver },
|
||||
volumes: hostvolumes,
|
||||
steps: [
|
||||
composer(phpversion, params),
|
||||
phpunit(phpversion, driver),
|
||||
],
|
||||
services: [
|
||||
{
|
||||
name: driver,
|
||||
image: 'mariadb:' + dbversion,
|
||||
environment: {
|
||||
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: 'yes',
|
||||
MARIADB_DATABASE: 'joomla_ut',
|
||||
MARIADB_ROOT_PASSWORD: '',
|
||||
# Provide MySQL environments variables for MariaDB < 10.2.
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes',
|
||||
MYSQL_DATABASE: 'joomla_ut',
|
||||
MYSQL_ROOT_PASSWORD: '',
|
||||
},
|
||||
ports: [
|
||||
{
|
||||
container: 3306,
|
||||
host: 3306,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
local pipeline_postgres(phpversion, driver, dbversion, params) = {
|
||||
kind: 'pipeline',
|
||||
name: 'PHP ' + phpversion + ' with PostgreSQL ' + dbversion + ' (' + driver + ')',
|
||||
environment: { DB: driver },
|
||||
volumes: hostvolumes,
|
||||
steps: [
|
||||
composer(phpversion, params),
|
||||
phpunit(phpversion, driver),
|
||||
],
|
||||
services: [
|
||||
{
|
||||
name: driver,
|
||||
image: 'postgres:' + dbversion,
|
||||
environment: {
|
||||
POSTGRES_HOST_AUTH_METHOD: 'trust',
|
||||
POSTGRES_PASSWORD: '',
|
||||
POSTGRES_USER: 'postgres',
|
||||
},
|
||||
ports: [
|
||||
{
|
||||
container: 5432,
|
||||
host: 5432,
|
||||
},
|
||||
],
|
||||
commands: [
|
||||
'psql -U postgres -c ',
|
||||
'psql -U postgres -d joomla_ut -a -f Tests/Stubs/Schema/pgsql.sql',
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
local pipeline_sqlsrv(phpversion, driver, dbversion, params) = {
|
||||
kind: 'pipeline',
|
||||
name: 'PHP ' + phpversion + ' with MS SQL Server ' + dbversion + ' (' + driver + ')',
|
||||
environment: { DB: driver },
|
||||
volumes: hostvolumes,
|
||||
steps: [
|
||||
composer(phpversion, params),
|
||||
phpunit_sqlsrv(phpversion),
|
||||
],
|
||||
services: [
|
||||
{
|
||||
name: driver,
|
||||
image: 'mcr.microsoft.com/mssql/server:' + dbversion,
|
||||
environment: {
|
||||
ACCEPT_EULA: 'Y',
|
||||
SA_PASSWORD: 'JoomlaFramework123',
|
||||
},
|
||||
ports: [
|
||||
{
|
||||
container: 1433,
|
||||
host: 1433,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
[
|
||||
{
|
||||
kind: 'pipeline',
|
||||
name: 'Codequality',
|
||||
volumes: hostvolumes,
|
||||
steps: [
|
||||
{
|
||||
name: 'composer',
|
||||
image: 'joomlaprojects/docker-images:php8.1',
|
||||
volumes: volumes,
|
||||
commands: [
|
||||
'php -v',
|
||||
'composer update'
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'phpcs',
|
||||
image: 'joomlaprojects/docker-images:php8.1',
|
||||
depends: [ 'composer' ],
|
||||
commands: [
|
||||
'vendor/bin/phpcs --standard=ruleset.xml src/',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'phan',
|
||||
image: 'joomlaprojects/docker-images:php8.1-ast',
|
||||
depends: [ 'composer' ],
|
||||
failure: 'ignore',
|
||||
commands: [
|
||||
'vendor/bin/phan'
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'phpstan',
|
||||
image: 'joomlaprojects/docker-images:php8.1',
|
||||
depends: [ 'composer' ],
|
||||
failure: 'ignore',
|
||||
commands: [
|
||||
'vendor/bin/phpstan analyse src',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'phploc',
|
||||
image: 'joomlaprojects/docker-images:php8.1',
|
||||
depends: [ 'composer' ],
|
||||
failure: 'ignore',
|
||||
commands: [
|
||||
'phploc src',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
pipeline_sqlite('8.1', 'sqlite', '--prefer-stable'),
|
||||
pipeline_sqlite('8.2', 'sqlite', '--prefer-stable'),
|
||||
pipeline_mysql('8.1', 'mysql', '5.7', '--prefer-stable'),
|
||||
pipeline_mysql('8.2', 'mysql', '5.7', '--prefer-stable'),
|
||||
pipeline_mysql('8.1', 'mysql', '8.0', '--prefer-stable'),
|
||||
pipeline_mysql('8.2', 'mysql', '8.0', '--prefer-stable'),
|
||||
pipeline_mysql('8.1', 'mysqli', '5.7', '--prefer-stable'),
|
||||
pipeline_mysql('8.2', 'mysqli', '5.7', '--prefer-stable'),
|
||||
pipeline_mysql('8.1', 'mysqli', '8.0', '--prefer-stable'),
|
||||
pipeline_mysql('8.2', 'mysqli', '8.0', '--prefer-stable'),
|
||||
pipeline_mariadb('8.1', 'mariadb', '10.2', '--prefer-stable'),
|
||||
pipeline_mariadb('8.2', 'mariadb', '10.2', '--prefer-stable'),
|
||||
pipeline_postgres('8.1', 'pgsql', '10', '--prefer-stable'),
|
||||
pipeline_postgres('8.2', 'pgsql', '10', '--prefer-stable'),
|
||||
pipeline_postgres('8.1', 'pgsql', '11', '--prefer-stable'),
|
||||
pipeline_postgres('8.2', 'pgsql', '11', '--prefer-stable'),
|
||||
pipeline_sqlsrv('8.1', 'sqlsrv', '2017-latest', '--prefer-stable'),
|
||||
pipeline_sqlsrv('8.2', 'sqlsrv', '2017-latest', '--prefer-stable'),
|
||||
]
|
||||
692
libraries/vendor/joomla/database/.drone.yml
vendored
Normal file
692
libraries/vendor/joomla/database/.drone.yml
vendored
Normal file
@ -0,0 +1,692 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: Codequality
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- composer update
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- vendor/bin/phpcs --standard=ruleset.xml src/
|
||||
depends:
|
||||
- composer
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: phpcs
|
||||
- commands:
|
||||
- vendor/bin/phan
|
||||
depends:
|
||||
- composer
|
||||
failure: ignore
|
||||
image: joomlaprojects/docker-images:php8.1-ast
|
||||
name: phan
|
||||
- commands:
|
||||
- vendor/bin/phpstan analyse src
|
||||
depends:
|
||||
- composer
|
||||
failure: ignore
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: phpstan
|
||||
- commands:
|
||||
- phploc src
|
||||
depends:
|
||||
- composer
|
||||
failure: ignore
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: phploc
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: sqlite
|
||||
kind: pipeline
|
||||
name: PHP 8.1 with SQLite (sqlite)
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri sqlite || true
|
||||
- vendor/bin/phpunit --configuration phpunit.sqlite.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: sqlite
|
||||
kind: pipeline
|
||||
name: PHP 8.2 with SQLite (sqlite)
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri sqlite || true
|
||||
- vendor/bin/phpunit --configuration phpunit.sqlite.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mysql
|
||||
kind: pipeline
|
||||
name: PHP 8.1 with MySQL 5.7 (mysql)
|
||||
services:
|
||||
- environment:
|
||||
ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: bitnami/mysql:5.7
|
||||
name: mysql
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mysql || true
|
||||
- sleep 20
|
||||
- vendor/bin/phpunit --configuration phpunit.mysql.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mysql
|
||||
kind: pipeline
|
||||
name: PHP 8.2 with MySQL 5.7 (mysql)
|
||||
services:
|
||||
- environment:
|
||||
ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: bitnami/mysql:5.7
|
||||
name: mysql
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mysql || true
|
||||
- sleep 20
|
||||
- vendor/bin/phpunit --configuration phpunit.mysql.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mysql
|
||||
kind: pipeline
|
||||
name: PHP 8.1 with MySQL 8.0 (mysql)
|
||||
services:
|
||||
- environment:
|
||||
ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: bitnami/mysql:8.0
|
||||
name: mysql
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mysql || true
|
||||
- sleep 20
|
||||
- vendor/bin/phpunit --configuration phpunit.mysql.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mysql
|
||||
kind: pipeline
|
||||
name: PHP 8.2 with MySQL 8.0 (mysql)
|
||||
services:
|
||||
- environment:
|
||||
ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: bitnami/mysql:8.0
|
||||
name: mysql
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mysql || true
|
||||
- sleep 20
|
||||
- vendor/bin/phpunit --configuration phpunit.mysql.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mysqli
|
||||
kind: pipeline
|
||||
name: PHP 8.1 with MySQL 5.7 (mysqli)
|
||||
services:
|
||||
- environment:
|
||||
ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: bitnami/mysql:5.7
|
||||
name: mysqli
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mysqli || true
|
||||
- sleep 20
|
||||
- vendor/bin/phpunit --configuration phpunit.mysqli.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mysqli
|
||||
kind: pipeline
|
||||
name: PHP 8.2 with MySQL 5.7 (mysqli)
|
||||
services:
|
||||
- environment:
|
||||
ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: bitnami/mysql:5.7
|
||||
name: mysqli
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mysqli || true
|
||||
- sleep 20
|
||||
- vendor/bin/phpunit --configuration phpunit.mysqli.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mysqli
|
||||
kind: pipeline
|
||||
name: PHP 8.1 with MySQL 8.0 (mysqli)
|
||||
services:
|
||||
- environment:
|
||||
ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: bitnami/mysql:8.0
|
||||
name: mysqli
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mysqli || true
|
||||
- sleep 20
|
||||
- vendor/bin/phpunit --configuration phpunit.mysqli.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mysqli
|
||||
kind: pipeline
|
||||
name: PHP 8.2 with MySQL 8.0 (mysqli)
|
||||
services:
|
||||
- environment:
|
||||
ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: bitnami/mysql:8.0
|
||||
name: mysqli
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mysqli || true
|
||||
- sleep 20
|
||||
- vendor/bin/phpunit --configuration phpunit.mysqli.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mariadb
|
||||
kind: pipeline
|
||||
name: PHP 8.1 with MariaDB 10.2 (mariadb)
|
||||
services:
|
||||
- environment:
|
||||
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "yes"
|
||||
MARIADB_DATABASE: joomla_ut
|
||||
MARIADB_ROOT_PASSWORD: ""
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: mariadb:10.2
|
||||
name: mariadb
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mariadb || true
|
||||
- vendor/bin/phpunit --configuration phpunit.mariadb.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: mariadb
|
||||
kind: pipeline
|
||||
name: PHP 8.2 with MariaDB 10.2 (mariadb)
|
||||
services:
|
||||
- environment:
|
||||
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "yes"
|
||||
MARIADB_DATABASE: joomla_ut
|
||||
MARIADB_ROOT_PASSWORD: ""
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_DATABASE: joomla_ut
|
||||
MYSQL_ROOT_PASSWORD: ""
|
||||
image: mariadb:10.2
|
||||
name: mariadb
|
||||
ports:
|
||||
- container: 3306
|
||||
host: 3306
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri mariadb || true
|
||||
- vendor/bin/phpunit --configuration phpunit.mariadb.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: pgsql
|
||||
kind: pipeline
|
||||
name: PHP 8.1 with PostgreSQL 10 (pgsql)
|
||||
services:
|
||||
- commands:
|
||||
- 'psql -U postgres -c '
|
||||
- psql -U postgres -d joomla_ut -a -f Tests/Stubs/Schema/pgsql.sql
|
||||
environment:
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
POSTGRES_PASSWORD: ""
|
||||
POSTGRES_USER: postgres
|
||||
image: postgres:10
|
||||
name: pgsql
|
||||
ports:
|
||||
- container: 5432
|
||||
host: 5432
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri pgsql || true
|
||||
- vendor/bin/phpunit --configuration phpunit.pgsql.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: pgsql
|
||||
kind: pipeline
|
||||
name: PHP 8.2 with PostgreSQL 10 (pgsql)
|
||||
services:
|
||||
- commands:
|
||||
- 'psql -U postgres -c '
|
||||
- psql -U postgres -d joomla_ut -a -f Tests/Stubs/Schema/pgsql.sql
|
||||
environment:
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
POSTGRES_PASSWORD: ""
|
||||
POSTGRES_USER: postgres
|
||||
image: postgres:10
|
||||
name: pgsql
|
||||
ports:
|
||||
- container: 5432
|
||||
host: 5432
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri pgsql || true
|
||||
- vendor/bin/phpunit --configuration phpunit.pgsql.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: pgsql
|
||||
kind: pipeline
|
||||
name: PHP 8.1 with PostgreSQL 11 (pgsql)
|
||||
services:
|
||||
- commands:
|
||||
- 'psql -U postgres -c '
|
||||
- psql -U postgres -d joomla_ut -a -f Tests/Stubs/Schema/pgsql.sql
|
||||
environment:
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
POSTGRES_PASSWORD: ""
|
||||
POSTGRES_USER: postgres
|
||||
image: postgres:11
|
||||
name: pgsql
|
||||
ports:
|
||||
- container: 5432
|
||||
host: 5432
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri pgsql || true
|
||||
- vendor/bin/phpunit --configuration phpunit.pgsql.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: pgsql
|
||||
kind: pipeline
|
||||
name: PHP 8.2 with PostgreSQL 11 (pgsql)
|
||||
services:
|
||||
- commands:
|
||||
- 'psql -U postgres -c '
|
||||
- psql -U postgres -d joomla_ut -a -f Tests/Stubs/Schema/pgsql.sql
|
||||
environment:
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
POSTGRES_PASSWORD: ""
|
||||
POSTGRES_USER: postgres
|
||||
image: postgres:11
|
||||
name: pgsql
|
||||
ports:
|
||||
- container: 5432
|
||||
host: 5432
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- php --ri pgsql || true
|
||||
- vendor/bin/phpunit --configuration phpunit.pgsql.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: sqlsrv
|
||||
kind: pipeline
|
||||
name: PHP 8.1 with MS SQL Server 2017-latest (sqlsrv)
|
||||
services:
|
||||
- environment:
|
||||
ACCEPT_EULA: "Y"
|
||||
SA_PASSWORD: JoomlaFramework123
|
||||
image: mcr.microsoft.com/mssql/server:2017-latest
|
||||
name: sqlsrv
|
||||
ports:
|
||||
- container: 1433
|
||||
host: 1433
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- apt-get update
|
||||
- apt-get install -y software-properties-common lsb-release gnupg
|
||||
- curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
|
||||
- echo "deb [arch=amd64,armhf,arm64] https://packages.microsoft.com/ubuntu/22.04/prod
|
||||
jammy main" >> /etc/apt/sources.list
|
||||
- apt-get update
|
||||
- ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev
|
||||
- pecl install sqlsrv && docker-php-ext-enable sqlsrv
|
||||
- pecl install pdo_sqlsrv && docker-php-ext-enable pdo_sqlsrv
|
||||
- php --ri sqlsrv
|
||||
- php --ri pdo_sqlsrv
|
||||
- vendor/bin/phpunit --configuration phpunit.sqlsrv.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.1
|
||||
name: PHPUnit with MS SQL Server
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
environment:
|
||||
DB: sqlsrv
|
||||
kind: pipeline
|
||||
name: PHP 8.2 with MS SQL Server 2017-latest (sqlsrv)
|
||||
services:
|
||||
- environment:
|
||||
ACCEPT_EULA: "Y"
|
||||
SA_PASSWORD: JoomlaFramework123
|
||||
image: mcr.microsoft.com/mssql/server:2017-latest
|
||||
name: sqlsrv
|
||||
ports:
|
||||
- container: 1433
|
||||
host: 1433
|
||||
steps:
|
||||
- commands:
|
||||
- php -v
|
||||
- sleep 20
|
||||
- composer update --prefer-stable
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: Composer
|
||||
volumes:
|
||||
- name: composer-cache
|
||||
path: /tmp/composer-cache
|
||||
- commands:
|
||||
- apt-get update
|
||||
- apt-get install -y software-properties-common lsb-release gnupg
|
||||
- curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
|
||||
- echo "deb [arch=amd64,armhf,arm64] https://packages.microsoft.com/ubuntu/22.04/prod
|
||||
jammy main" >> /etc/apt/sources.list
|
||||
- apt-get update
|
||||
- ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev
|
||||
- pecl install sqlsrv && docker-php-ext-enable sqlsrv
|
||||
- pecl install pdo_sqlsrv && docker-php-ext-enable pdo_sqlsrv
|
||||
- php --ri sqlsrv
|
||||
- php --ri pdo_sqlsrv
|
||||
- vendor/bin/phpunit --configuration phpunit.sqlsrv.xml.dist --testdox
|
||||
image: joomlaprojects/docker-images:php8.2
|
||||
name: PHPUnit with MS SQL Server
|
||||
volumes:
|
||||
- host:
|
||||
path: /tmp/composer-cache
|
||||
name: composer-cache
|
||||
---
|
||||
kind: signature
|
||||
hmac: e511351199fd2fa0a45c01a540e0c31ecbe7c72b30075fa2dea06b11ca5c7f58
|
||||
|
||||
...
|
||||
340
libraries/vendor/joomla/database/LICENSE
vendored
Normal file
340
libraries/vendor/joomla/database/LICENSE
vendored
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
19
libraries/vendor/joomla/database/phpunit.appveyor_sql2012sp1.xml.dist
vendored
Normal file
19
libraries/vendor/joomla/database/phpunit.appveyor_sql2012sp1.xml.dist
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="Tests/bootstrap.php" colors="false">
|
||||
<php>
|
||||
<env name="JOOMLA_TEST_DB_DRIVER" value="sqlsrv" />
|
||||
<env name="JOOMLA_TEST_DB_HOST" value="(local)\SQL2012SP1" />
|
||||
<env name="JOOMLA_TEST_DB_PORT" value="" />
|
||||
<env name="JOOMLA_TEST_DB_USER" value="sa" />
|
||||
<env name="JOOMLA_TEST_DB_PASSWORD" value="Password12!" />
|
||||
<env name="JOOMLA_TEST_DB_DATABASE" value="joomla_ut" />
|
||||
<env name="JOOMLA_TEST_DB_PREFIX" value="" />
|
||||
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>Tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
19
libraries/vendor/joomla/database/phpunit.appveyor_sql2014.xml.dist
vendored
Normal file
19
libraries/vendor/joomla/database/phpunit.appveyor_sql2014.xml.dist
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="Tests/bootstrap.php" colors="false">
|
||||
<php>
|
||||
<env name="JOOMLA_TEST_DB_DRIVER" value="sqlsrv" />
|
||||
<env name="JOOMLA_TEST_DB_HOST" value="(local)\SQL2014" />
|
||||
<env name="JOOMLA_TEST_DB_PORT" value="" />
|
||||
<env name="JOOMLA_TEST_DB_USER" value="sa" />
|
||||
<env name="JOOMLA_TEST_DB_PASSWORD" value="Password12!" />
|
||||
<env name="JOOMLA_TEST_DB_DATABASE" value="joomla_ut" />
|
||||
<env name="JOOMLA_TEST_DB_PREFIX" value="" />
|
||||
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>Tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
19
libraries/vendor/joomla/database/phpunit.appveyor_sql2017.xml.dist
vendored
Normal file
19
libraries/vendor/joomla/database/phpunit.appveyor_sql2017.xml.dist
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="Tests/bootstrap.php" colors="false">
|
||||
<php>
|
||||
<env name="JOOMLA_TEST_DB_DRIVER" value="sqlsrv" />
|
||||
<env name="JOOMLA_TEST_DB_HOST" value="(local)\SQL2017" />
|
||||
<env name="JOOMLA_TEST_DB_PORT" value="" />
|
||||
<env name="JOOMLA_TEST_DB_USER" value="sa" />
|
||||
<env name="JOOMLA_TEST_DB_PASSWORD" value="Password12!" />
|
||||
<env name="JOOMLA_TEST_DB_DATABASE" value="joomla_ut" />
|
||||
<env name="JOOMLA_TEST_DB_PREFIX" value="" />
|
||||
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>Tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
19
libraries/vendor/joomla/database/phpunit.mariadb.xml.dist
vendored
Normal file
19
libraries/vendor/joomla/database/phpunit.mariadb.xml.dist
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="Tests/bootstrap.php" colors="false">
|
||||
<php>
|
||||
<env name="JOOMLA_TEST_DB_DRIVER" value="mysqli" />
|
||||
<env name="JOOMLA_TEST_DB_HOST" value="mariadb" />
|
||||
<env name="JOOMLA_TEST_DB_PORT" value="3306" />
|
||||
<env name="JOOMLA_TEST_DB_USER" value="root" />
|
||||
<env name="JOOMLA_TEST_DB_PASSWORD" value="" />
|
||||
<env name="JOOMLA_TEST_DB_DATABASE" value="joomla_ut" />
|
||||
<env name="JOOMLA_TEST_DB_PREFIX" value="" />
|
||||
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>Tests/Mysqli</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
19
libraries/vendor/joomla/database/phpunit.mysql.xml.dist
vendored
Normal file
19
libraries/vendor/joomla/database/phpunit.mysql.xml.dist
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="Tests/bootstrap.php" colors="false">
|
||||
<php>
|
||||
<env name="JOOMLA_TEST_DB_DRIVER" value="mysql" />
|
||||
<env name="JOOMLA_TEST_DB_HOST" value="mysql" />
|
||||
<env name="JOOMLA_TEST_DB_PORT" value="3306" />
|
||||
<env name="JOOMLA_TEST_DB_USER" value="root" />
|
||||
<env name="JOOMLA_TEST_DB_PASSWORD" value="" />
|
||||
<env name="JOOMLA_TEST_DB_DATABASE" value="joomla_ut" />
|
||||
<env name="JOOMLA_TEST_DB_PREFIX" value="" />
|
||||
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>Tests/Mysql</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
19
libraries/vendor/joomla/database/phpunit.mysqli.xml.dist
vendored
Normal file
19
libraries/vendor/joomla/database/phpunit.mysqli.xml.dist
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="Tests/bootstrap.php" colors="false">
|
||||
<php>
|
||||
<env name="JOOMLA_TEST_DB_DRIVER" value="mysqli" />
|
||||
<env name="JOOMLA_TEST_DB_HOST" value="mysqli" />
|
||||
<env name="JOOMLA_TEST_DB_PORT" value="3306" />
|
||||
<env name="JOOMLA_TEST_DB_USER" value="root" />
|
||||
<env name="JOOMLA_TEST_DB_PASSWORD" value="" />
|
||||
<env name="JOOMLA_TEST_DB_DATABASE" value="joomla_ut" />
|
||||
<env name="JOOMLA_TEST_DB_PREFIX" value="" />
|
||||
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>Tests/Mysqli</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
20
libraries/vendor/joomla/database/phpunit.pgsql.xml.dist
vendored
Normal file
20
libraries/vendor/joomla/database/phpunit.pgsql.xml.dist
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="Tests/bootstrap.php" colors="false">
|
||||
<php>
|
||||
<env name="JOOMLA_TEST_DB_DRIVER" value="pgsql" />
|
||||
<env name="JOOMLA_TEST_DB_HOST" value="pgsql" />
|
||||
<env name="JOOMLA_TEST_DB_PORT" value="5433" />
|
||||
<env name="JOOMLA_TEST_DB_USER" value="postgres" />
|
||||
<env name="JOOMLA_TEST_DB_PASSWORD" value="" />
|
||||
<env name="JOOMLA_TEST_DB_DATABASE" value="joomla_ut" />
|
||||
<env name="JOOMLA_TEST_DB_PREFIX" value="" />
|
||||
<env name="JOOMLA_TEST_DB_SELECT" value="yes" />
|
||||
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>Tests/Pgsql</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
19
libraries/vendor/joomla/database/phpunit.sqlite.xml.dist
vendored
Normal file
19
libraries/vendor/joomla/database/phpunit.sqlite.xml.dist
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="Tests/bootstrap.php" colors="false">
|
||||
<php>
|
||||
<env name="JOOMLA_TEST_DB_DRIVER" value="sqlite" />
|
||||
<env name="JOOMLA_TEST_DB_HOST" value="" />
|
||||
<env name="JOOMLA_TEST_DB_PORT" value="" />
|
||||
<env name="JOOMLA_TEST_DB_USER" value="" />
|
||||
<env name="JOOMLA_TEST_DB_PASSWORD" value="" />
|
||||
<env name="JOOMLA_TEST_DB_DATABASE" value=":memory:" />
|
||||
<env name="JOOMLA_TEST_DB_PREFIX" value="" />
|
||||
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>Tests/Sqlite</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
19
libraries/vendor/joomla/database/phpunit.sqlsrv.xml.dist
vendored
Normal file
19
libraries/vendor/joomla/database/phpunit.sqlsrv.xml.dist
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="Tests/bootstrap.php" colors="false">
|
||||
<php>
|
||||
<env name="JOOMLA_TEST_DB_DRIVER" value="sqlsrv" />
|
||||
<env name="JOOMLA_TEST_DB_HOST" value="sqlsrv" />
|
||||
<env name="JOOMLA_TEST_DB_PORT" value="1433" />
|
||||
<env name="JOOMLA_TEST_DB_USER" value="sa" />
|
||||
<env name="JOOMLA_TEST_DB_PASSWORD" value="JoomlaFramework123" />
|
||||
<env name="JOOMLA_TEST_DB_DATABASE" value="joomla_ut" />
|
||||
<env name="JOOMLA_TEST_DB_PREFIX" value="" />
|
||||
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>Tests/Sqlsrv</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
168
libraries/vendor/joomla/database/src/Command/ExportCommand.php
vendored
Normal file
168
libraries/vendor/joomla/database/src/Command/ExportCommand.php
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Command;
|
||||
|
||||
use Joomla\Archive\Archive;
|
||||
use Joomla\Archive\Zip;
|
||||
use Joomla\Console\Command\AbstractCommand;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\Exception\UnsupportedAdapterException;
|
||||
use Joomla\Filesystem\File;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
/**
|
||||
* Console command for exporting the database
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class ExportCommand extends AbstractCommand
|
||||
{
|
||||
/**
|
||||
* The default command name
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected static $defaultName = 'database:export';
|
||||
|
||||
/**
|
||||
* Database connector
|
||||
*
|
||||
* @var DatabaseDriver
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* Instantiate the command.
|
||||
*
|
||||
* @param DatabaseDriver $db Database connector
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to execute the command.
|
||||
*
|
||||
* @param InputInterface $input The input to inject into the command.
|
||||
* @param OutputInterface $output The output to inject into the command.
|
||||
*
|
||||
* @return integer The command exit code
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$symfonyStyle = new SymfonyStyle($input, $output);
|
||||
|
||||
$symfonyStyle->title('Exporting Database');
|
||||
|
||||
$totalTime = microtime(true);
|
||||
|
||||
if (!class_exists(File::class)) {
|
||||
$symfonyStyle->error('The "joomla/filesystem" Composer package is not installed, cannot create an export.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Make sure the database supports exports before we get going
|
||||
try {
|
||||
$exporter = $this->db->getExporter()
|
||||
->withStructure();
|
||||
} catch (UnsupportedAdapterException $e) {
|
||||
$symfonyStyle->error(sprintf('The "%s" database driver does not support exporting data.', $this->db->getName()));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$folderPath = $input->getOption('folder');
|
||||
$tableName = $input->getOption('table');
|
||||
$zip = $input->getOption('zip');
|
||||
|
||||
$zipFile = $folderPath . '/data_exported_' . date("Y-m-d\TH-i-s") . '.zip';
|
||||
$tables = $this->db->getTableList();
|
||||
$prefix = $this->db->getPrefix();
|
||||
|
||||
if ($tableName) {
|
||||
if (!\in_array($tableName, $tables)) {
|
||||
$symfonyStyle->error(sprintf('The %s table does not exist in the database.', $tableName));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$tables = [$tableName];
|
||||
}
|
||||
|
||||
if ($zip) {
|
||||
if (!class_exists(Archive::class)) {
|
||||
$symfonyStyle->error('The "joomla/archive" Composer package is not installed, cannot create ZIP files.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** @var Zip $zipArchive */
|
||||
$zipArchive = (new Archive())->getAdapter('zip');
|
||||
}
|
||||
|
||||
foreach ($tables as $table) {
|
||||
// If an empty prefix is in use then we will dump all tables, otherwise the prefix must match
|
||||
if (strlen($prefix) === 0 || strpos(substr($table, 0, strlen($prefix)), $prefix) !== false) {
|
||||
$taskTime = microtime(true);
|
||||
$filename = $folderPath . '/' . $table . '.xml';
|
||||
|
||||
$symfonyStyle->text(sprintf('Processing the %s table', $table));
|
||||
|
||||
$data = (string) $exporter->from($table)->withData(true);
|
||||
|
||||
if (file_exists($filename)) {
|
||||
File::delete($filename);
|
||||
}
|
||||
|
||||
File::write($filename, $data);
|
||||
|
||||
if ($zip) {
|
||||
$zipFilesArray = [['name' => $table . '.xml', 'data' => $data]];
|
||||
$zipArchive->create($zipFile, $zipFilesArray);
|
||||
File::delete($filename);
|
||||
}
|
||||
|
||||
$symfonyStyle->text(sprintf('Exported data for %s in %d seconds', $table, round(microtime(true) - $taskTime, 3)));
|
||||
}
|
||||
}
|
||||
|
||||
$symfonyStyle->success(sprintf('Export completed in %d seconds', round(microtime(true) - $totalTime, 3)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the command.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Export the database');
|
||||
$this->addOption('folder', null, InputOption::VALUE_OPTIONAL, 'Path to write the export files to', '.');
|
||||
$this->addOption('table', null, InputOption::VALUE_REQUIRED, 'The name of the database table to export');
|
||||
$this->addOption('zip', null, InputOption::VALUE_NONE, 'Flag indicating the export will be saved to a ZIP archive');
|
||||
}
|
||||
}
|
||||
251
libraries/vendor/joomla/database/src/Command/ImportCommand.php
vendored
Normal file
251
libraries/vendor/joomla/database/src/Command/ImportCommand.php
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
// phpcs:disable Generic.PHP.DeprecatedFunctions.Deprecated
|
||||
|
||||
namespace Joomla\Database\Command;
|
||||
|
||||
use Joomla\Archive\Archive;
|
||||
use Joomla\Archive\Exception\UnknownArchiveException;
|
||||
use Joomla\Console\Command\AbstractCommand;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use Joomla\Database\Exception\UnsupportedAdapterException;
|
||||
use Joomla\Filesystem\Exception\FilesystemException;
|
||||
use Joomla\Filesystem\File;
|
||||
use Joomla\Filesystem\Folder;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
/**
|
||||
* Console command for importing the database
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class ImportCommand extends AbstractCommand
|
||||
{
|
||||
/**
|
||||
* The default command name
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected static $defaultName = 'database:import';
|
||||
|
||||
/**
|
||||
* Database connector
|
||||
*
|
||||
* @var DatabaseDriver
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* Instantiate the command.
|
||||
*
|
||||
* @param DatabaseDriver $db Database connector
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the zip file contains database export files
|
||||
*
|
||||
* @param string $archive A zip archive to analyze
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
private function checkZipFile(string $archive): void
|
||||
{
|
||||
if (!extension_loaded('zip')) {
|
||||
throw new \RuntimeException('The PHP zip extension is not installed or is disabled');
|
||||
}
|
||||
|
||||
$zip = zip_open($archive);
|
||||
|
||||
if (!\is_resource($zip)) {
|
||||
throw new \RuntimeException('Unable to open archive');
|
||||
}
|
||||
|
||||
while ($file = @zip_read($zip)) {
|
||||
if (strpos(zip_entry_name($file), $this->db->getPrefix()) === false) {
|
||||
zip_entry_close($file);
|
||||
@zip_close($zip);
|
||||
|
||||
throw new \RuntimeException('Unable to find table matching database prefix');
|
||||
}
|
||||
|
||||
zip_entry_close($file);
|
||||
}
|
||||
|
||||
@zip_close($zip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to execute the command.
|
||||
*
|
||||
* @param InputInterface $input The input to inject into the command.
|
||||
* @param OutputInterface $output The output to inject into the command.
|
||||
*
|
||||
* @return integer The command exit code
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$symfonyStyle = new SymfonyStyle($input, $output);
|
||||
|
||||
$symfonyStyle->title('Importing Database');
|
||||
|
||||
$totalTime = microtime(true);
|
||||
|
||||
// Make sure the database supports imports before we get going
|
||||
try {
|
||||
$importer = $this->db->getImporter()
|
||||
->withStructure()
|
||||
->asXml();
|
||||
} catch (UnsupportedAdapterException $e) {
|
||||
$symfonyStyle->error(sprintf('The "%s" database driver does not support importing data.', $this->db->getName()));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$folderPath = $input->getOption('folder');
|
||||
$tableName = $input->getOption('table');
|
||||
$zipFile = $input->getOption('zip');
|
||||
|
||||
if ($zipFile) {
|
||||
if (!class_exists(File::class)) {
|
||||
$symfonyStyle->error('The "joomla/filesystem" Composer package is not installed, cannot process ZIP files.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!class_exists(Archive::class)) {
|
||||
$symfonyStyle->error('The "joomla/archive" Composer package is not installed, cannot process ZIP files.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$zipPath = $folderPath . '/' . $zipFile;
|
||||
|
||||
try {
|
||||
$this->checkZipFile($zipPath);
|
||||
} catch (\RuntimeException $e) {
|
||||
$symfonyStyle->error($e->getMessage());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$folderPath .= File::stripExt($zipFile);
|
||||
|
||||
try {
|
||||
Folder::create($folderPath);
|
||||
} catch (FilesystemException $e) {
|
||||
$symfonyStyle->error($e->getMessage());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
(new Archive())->extract($zipPath, $folderPath);
|
||||
} catch (UnknownArchiveException $e) {
|
||||
$symfonyStyle->error($e->getMessage());
|
||||
Folder::delete($folderPath);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tableName) {
|
||||
$tables = [$tableName . '.xml'];
|
||||
} else {
|
||||
$tables = Folder::files($folderPath, '\.xml$');
|
||||
}
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$taskTime = microtime(true);
|
||||
$percorso = $folderPath . '/' . $table;
|
||||
|
||||
// Check file
|
||||
if (!file_exists($percorso)) {
|
||||
$symfonyStyle->error(sprintf('The %s file does not exist.', $table));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$tableName = str_replace('.xml', '', $table);
|
||||
$symfonyStyle->text(sprintf('Importing %1$s from %2$s', $tableName, $table));
|
||||
|
||||
$importer->from(file_get_contents($percorso));
|
||||
|
||||
$symfonyStyle->text(sprintf('Processing the %s table', $tableName));
|
||||
|
||||
try {
|
||||
$this->db->dropTable($tableName, true);
|
||||
} catch (ExecutionFailureException $e) {
|
||||
$symfonyStyle->error(sprintf('Error executing the DROP TABLE statement for %1$s: %2$s', $tableName, $e->getMessage()));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
$importer->mergeStructure();
|
||||
} catch (\Exception $e) {
|
||||
$symfonyStyle->error(sprintf('Error merging the structure for %1$s: %2$s', $tableName, $e->getMessage()));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
$importer->importData();
|
||||
} catch (\Exception $e) {
|
||||
$symfonyStyle->error(sprintf('Error importing the data for %1$s: %2$s', $tableName, $e->getMessage()));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$symfonyStyle->text(sprintf('Imported data for %s in %d seconds', $table, round(microtime(true) - $taskTime, 3)));
|
||||
}
|
||||
|
||||
if ($zipFile) {
|
||||
Folder::delete($folderPath);
|
||||
}
|
||||
|
||||
$symfonyStyle->success(sprintf('Import completed in %d seconds', round(microtime(true) - $totalTime, 3)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the command.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('Import the database');
|
||||
$this->addOption('folder', null, InputOption::VALUE_OPTIONAL, 'Path to the folder containing files to import', '.');
|
||||
$this->addOption('zip', null, InputOption::VALUE_REQUIRED, 'The name of a ZIP file to import');
|
||||
$this->addOption('table', null, InputOption::VALUE_REQUIRED, 'The name of the database table to import');
|
||||
}
|
||||
}
|
||||
29
libraries/vendor/joomla/database/src/DatabaseAwareInterface.php
vendored
Normal file
29
libraries/vendor/joomla/database/src/DatabaseAwareInterface.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2022 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Defines the interface for a DatabaseInterface aware class.
|
||||
*
|
||||
* @since 2.1.0
|
||||
*/
|
||||
interface DatabaseAwareInterface
|
||||
{
|
||||
/**
|
||||
* Set the database.
|
||||
*
|
||||
* @param DatabaseInterface $db The database.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public function setDatabase(DatabaseInterface $db): void;
|
||||
}
|
||||
59
libraries/vendor/joomla/database/src/DatabaseAwareTrait.php
vendored
Normal file
59
libraries/vendor/joomla/database/src/DatabaseAwareTrait.php
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2022 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
use Joomla\Database\Exception\DatabaseNotFoundException;
|
||||
|
||||
/**
|
||||
* Defines the trait for a Database Aware Class.
|
||||
*
|
||||
* @since 2.1.0
|
||||
*/
|
||||
trait DatabaseAwareTrait
|
||||
{
|
||||
/**
|
||||
* Database
|
||||
*
|
||||
* @var DatabaseInterface
|
||||
* @since 2.1.0
|
||||
*/
|
||||
private $databaseAwareTraitDatabase;
|
||||
|
||||
/**
|
||||
* Get the database.
|
||||
*
|
||||
* @return DatabaseInterface
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @throws DatabaseNotFoundException May be thrown if the database has not been set.
|
||||
*/
|
||||
protected function getDatabase(): DatabaseInterface
|
||||
{
|
||||
if ($this->databaseAwareTraitDatabase) {
|
||||
return $this->databaseAwareTraitDatabase;
|
||||
}
|
||||
|
||||
throw new DatabaseNotFoundException('Database not set in ' . \get_class($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database.
|
||||
*
|
||||
* @param DatabaseInterface $db The database.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public function setDatabase(DatabaseInterface $db): void
|
||||
{
|
||||
$this->databaseAwareTraitDatabase = $db;
|
||||
}
|
||||
}
|
||||
1896
libraries/vendor/joomla/database/src/DatabaseDriver.php
vendored
Normal file
1896
libraries/vendor/joomla/database/src/DatabaseDriver.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
47
libraries/vendor/joomla/database/src/DatabaseEvents.php
vendored
Normal file
47
libraries/vendor/joomla/database/src/DatabaseEvents.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Class defining the events dispatched by the database API
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
final class DatabaseEvents
|
||||
{
|
||||
/**
|
||||
* Private constructor to prevent instantiation of this class
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Database event which is dispatched after the connection to the database server is opened.
|
||||
*
|
||||
* Listeners to this event receive a `Joomla\Database\Event\ConnectionEvent` object.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const POST_CONNECT = 'onAfterConnect';
|
||||
|
||||
/**
|
||||
* Database event which is dispatched after the connection to the database server is closed.
|
||||
*
|
||||
* Listeners to this event receive a `Joomla\Database\Event\ConnectionEvent` object.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const POST_DISCONNECT = 'onAfterDisconnect';
|
||||
}
|
||||
308
libraries/vendor/joomla/database/src/DatabaseExporter.php
vendored
Normal file
308
libraries/vendor/joomla/database/src/DatabaseExporter.php
vendored
Normal file
@ -0,0 +1,308 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Joomla Framework Database Exporter Class
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract class DatabaseExporter
|
||||
{
|
||||
/**
|
||||
* The type of output format.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $asFormat = 'xml';
|
||||
|
||||
/**
|
||||
* An array of cached data.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $cache = ['columns' => [], 'keys' => []];
|
||||
|
||||
/**
|
||||
* The database connector to use for exporting structure and/or data.
|
||||
*
|
||||
* @var DatabaseInterface
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* An array input sources (table names).
|
||||
*
|
||||
* @var string[]
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $from = [];
|
||||
|
||||
/**
|
||||
* An array of options for the exporter.
|
||||
*
|
||||
* @var \stdClass
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Sets up the default options for the exporter.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->options = new \stdClass();
|
||||
|
||||
// Set up the class defaults:
|
||||
|
||||
// Export not only structure
|
||||
$this->withStructure();
|
||||
$this->withData();
|
||||
|
||||
// Export as xml.
|
||||
$this->asXml();
|
||||
|
||||
// Default destination is a string using $output = (string) $exporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic function to exports the data to a string.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$buffer = '';
|
||||
|
||||
try {
|
||||
// Check everything is ok to run first.
|
||||
$this->check();
|
||||
|
||||
// Get the format.
|
||||
switch ($this->asFormat) {
|
||||
case 'xml':
|
||||
default:
|
||||
$buffer = $this->buildXml();
|
||||
|
||||
break;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output option for the exporter to XML format.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function asXml()
|
||||
{
|
||||
$this->asFormat = 'xml';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XML data for the tables to export.
|
||||
*
|
||||
* @return string An XML string
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
abstract protected function buildXml();
|
||||
|
||||
/**
|
||||
* Builds the XML structure to export.
|
||||
*
|
||||
* @return array An array of XML lines (strings).
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
abstract protected function buildXmlStructure();
|
||||
|
||||
/**
|
||||
* Checks if all data and options are in order prior to exporting.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception if an error is encountered.
|
||||
*/
|
||||
abstract public function check();
|
||||
|
||||
/**
|
||||
* Specifies a list of table names to export.
|
||||
*
|
||||
* @param string[]|string $from The name of a single table, or an array of the table names to export.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function from($from)
|
||||
{
|
||||
if (\is_string($from)) {
|
||||
$this->from = [$from];
|
||||
} elseif (\is_array($from)) {
|
||||
$this->from = $from;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('The exporter requires either a single table name or array of table names');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the generic name of the table, converting the database prefix to the wildcard string.
|
||||
*
|
||||
* @param string $table The name of the table.
|
||||
*
|
||||
* @return string The name of the table with the database prefix replaced with #__.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getGenericTableName($table)
|
||||
{
|
||||
$prefix = $this->db->getPrefix();
|
||||
|
||||
// Replace the magic prefix if found.
|
||||
return preg_replace("|^$prefix|", '#__', $table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database connector to use for importing structure and/or data.
|
||||
*
|
||||
* @param DatabaseInterface $db The database connector.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function setDbo(DatabaseInterface $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an internal option to export the structure of the input table(s).
|
||||
*
|
||||
* @param boolean $setting True to export the structure, false to not.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function withStructure($setting = true)
|
||||
{
|
||||
$this->options->withStructure = (bool) $setting;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an internal option to export the data of the input table(s).
|
||||
*
|
||||
* @param boolean $setting True to export the data, false to not.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function withData($setting = false)
|
||||
{
|
||||
$this->options->withData = (bool) $setting;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XML data to export.
|
||||
*
|
||||
* @return array An array of XML lines (strings).
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXmlData()
|
||||
{
|
||||
$buffer = [];
|
||||
|
||||
foreach ($this->from as $table) {
|
||||
// Replace the magic prefix if found.
|
||||
$table = $this->getGenericTableName($table);
|
||||
|
||||
// Get the details columns information.
|
||||
$fields = $this->db->getTableColumns($table, false);
|
||||
$colblob = [];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
// Catch blob for conversion xml
|
||||
if ($field->Type == 'mediumblob') {
|
||||
$colblob[] = $field->Field;
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->setQuery(
|
||||
$this->db->getQuery(true)
|
||||
->select($this->db->quoteName(array_keys($fields)))
|
||||
->from($this->db->quoteName($table))
|
||||
);
|
||||
|
||||
$rows = $this->db->loadObjectList();
|
||||
|
||||
if (!count($rows)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$buffer[] = ' <table_data name="' . $table . '">';
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$buffer[] = ' <row>';
|
||||
|
||||
foreach ($row as $key => $value) {
|
||||
if (!in_array($key, $colblob)) {
|
||||
if (is_null($value)) {
|
||||
$buffer[] = ' <field name="' . $key . '" value_is_null></field>';
|
||||
} else {
|
||||
$buffer[] = ' <field name="' . $key . '">' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</field>';
|
||||
}
|
||||
} else {
|
||||
$buffer[] = ' <field name="' . $key . '">' . base64_encode($value) . '</field>';
|
||||
}
|
||||
}
|
||||
|
||||
$buffer[] = ' </row>';
|
||||
}
|
||||
|
||||
$buffer[] = ' </table_data>';
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
}
|
||||
171
libraries/vendor/joomla/database/src/DatabaseFactory.php
vendored
Normal file
171
libraries/vendor/joomla/database/src/DatabaseFactory.php
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Joomla Framework Database Factory class
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class DatabaseFactory
|
||||
{
|
||||
/**
|
||||
* Method to return a database driver based on the given options.
|
||||
*
|
||||
* There are three global options and then the rest are specific to the database driver. The 'database' option determines which database is to
|
||||
* be used for the connection. The 'select' option determines whether the connector should automatically select the chosen database.
|
||||
*
|
||||
* @param string $name Name of the database driver you'd like to instantiate
|
||||
* @param array $options Parameters to be passed to the database driver.
|
||||
*
|
||||
* @return DatabaseInterface
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws Exception\UnsupportedAdapterException if there is not a compatible database driver
|
||||
*/
|
||||
public function getDriver(string $name = 'mysqli', array $options = []): DatabaseInterface
|
||||
{
|
||||
// Sanitize the database connector options.
|
||||
$options['driver'] = preg_replace('/[^A-Z0-9_\.-]/i', '', $name);
|
||||
$options['database'] = $options['database'] ?? null;
|
||||
$options['select'] = $options['select'] ?? true;
|
||||
$options['factory'] = $options['factory'] ?? $this;
|
||||
|
||||
// Derive the class name from the driver.
|
||||
$class = __NAMESPACE__ . '\\' . ucfirst(strtolower($options['driver'])) . '\\' . ucfirst(strtolower($options['driver'])) . 'Driver';
|
||||
|
||||
// If the class still doesn't exist we have nothing left to do but throw an exception. We did our best.
|
||||
if (!class_exists($class)) {
|
||||
throw new Exception\UnsupportedAdapterException(sprintf('Unable to load Database Driver: %s', $options['driver']));
|
||||
}
|
||||
|
||||
return new $class($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an exporter class object.
|
||||
*
|
||||
* @param string $name Name of the driver you want an exporter for.
|
||||
* @param DatabaseInterface|null $db Optional database driver to inject into the query object.
|
||||
*
|
||||
* @return DatabaseExporter
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws Exception\UnsupportedAdapterException if there is not a compatible database exporter
|
||||
*/
|
||||
public function getExporter(string $name, ?DatabaseInterface $db = null): DatabaseExporter
|
||||
{
|
||||
// Derive the class name from the driver.
|
||||
$class = __NAMESPACE__ . '\\' . ucfirst(strtolower($name)) . '\\' . ucfirst(strtolower($name)) . 'Exporter';
|
||||
|
||||
// Make sure we have an exporter class for this driver.
|
||||
if (!class_exists($class)) {
|
||||
// If it doesn't exist we are at an impasse so throw an exception.
|
||||
throw new Exception\UnsupportedAdapterException('Database Exporter not found.');
|
||||
}
|
||||
|
||||
/** @var DatabaseExporter $o */
|
||||
$o = new $class();
|
||||
|
||||
if ($db) {
|
||||
$o->setDbo($db);
|
||||
}
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an importer class object.
|
||||
*
|
||||
* @param string $name Name of the driver you want an importer for.
|
||||
* @param DatabaseInterface|null $db Optional database driver to inject into the query object.
|
||||
*
|
||||
* @return DatabaseImporter
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws Exception\UnsupportedAdapterException if there is not a compatible database importer
|
||||
*/
|
||||
public function getImporter(string $name, ?DatabaseInterface $db = null): DatabaseImporter
|
||||
{
|
||||
// Derive the class name from the driver.
|
||||
$class = __NAMESPACE__ . '\\' . ucfirst(strtolower($name)) . '\\' . ucfirst(strtolower($name)) . 'Importer';
|
||||
|
||||
// Make sure we have an importer class for this driver.
|
||||
if (!class_exists($class)) {
|
||||
// If it doesn't exist we are at an impasse so throw an exception.
|
||||
throw new Exception\UnsupportedAdapterException('Database importer not found.');
|
||||
}
|
||||
|
||||
/** @var DatabaseImporter $o */
|
||||
$o = new $class();
|
||||
|
||||
if ($db) {
|
||||
$o->setDbo($db);
|
||||
}
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new iterator on the current query.
|
||||
*
|
||||
* @param string $name Name of the driver you want an iterator for.
|
||||
* @param StatementInterface $statement Statement holding the result set to be iterated.
|
||||
* @param string|null $column An optional column to use as the iterator key.
|
||||
* @param string $class The class of object that is returned.
|
||||
*
|
||||
* @return DatabaseIterator
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getIterator(
|
||||
string $name,
|
||||
StatementInterface $statement,
|
||||
?string $column = null,
|
||||
string $class = \stdClass::class
|
||||
): DatabaseIterator {
|
||||
// Derive the class name from the driver.
|
||||
$iteratorClass = __NAMESPACE__ . '\\' . ucfirst($name) . '\\' . ucfirst($name) . 'Iterator';
|
||||
|
||||
// Make sure we have an iterator class for this driver.
|
||||
if (!class_exists($iteratorClass)) {
|
||||
// We can work with the base iterator class so use that
|
||||
$iteratorClass = DatabaseIterator::class;
|
||||
}
|
||||
|
||||
// Return a new iterator
|
||||
return new $iteratorClass($statement, $column, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current query object or a new Query object.
|
||||
*
|
||||
* @param string $name Name of the driver you want an query object for.
|
||||
* @param DatabaseInterface|null $db Optional database driver to inject into the query object.
|
||||
*
|
||||
* @return QueryInterface
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws Exception\UnsupportedAdapterException if there is not a compatible database query object
|
||||
*/
|
||||
public function getQuery(string $name, ?DatabaseInterface $db = null): QueryInterface
|
||||
{
|
||||
// Derive the class name from the driver.
|
||||
$class = __NAMESPACE__ . '\\' . ucfirst(strtolower($name)) . '\\' . ucfirst(strtolower($name)) . 'Query';
|
||||
|
||||
// Make sure we have a query class for this driver.
|
||||
if (!class_exists($class)) {
|
||||
// If it doesn't exist we are at an impasse so throw an exception.
|
||||
throw new Exception\UnsupportedAdapterException('Database Query class not found');
|
||||
}
|
||||
|
||||
return new $class($db);
|
||||
}
|
||||
}
|
||||
376
libraries/vendor/joomla/database/src/DatabaseImporter.php
vendored
Normal file
376
libraries/vendor/joomla/database/src/DatabaseImporter.php
vendored
Normal file
@ -0,0 +1,376 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Joomla Framework Database Importer Class
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract class DatabaseImporter
|
||||
{
|
||||
/**
|
||||
* An array of cached data.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $cache = ['columns' => [], 'keys' => []];
|
||||
|
||||
/**
|
||||
* The database connector to use for exporting structure and/or data.
|
||||
*
|
||||
* @var DatabaseInterface
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* The input source.
|
||||
*
|
||||
* @var mixed
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $from = [];
|
||||
|
||||
/**
|
||||
* The type of input format.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $asFormat = 'xml';
|
||||
|
||||
/**
|
||||
* An array of options for the exporter.
|
||||
*
|
||||
* @var \stdClass
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Sets up the default options for the importer.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->options = new \stdClass();
|
||||
|
||||
// Set up the class defaults:
|
||||
|
||||
// Import with only structure
|
||||
$this->withStructure();
|
||||
|
||||
// Export as XML.
|
||||
$this->asXml();
|
||||
|
||||
// Default destination is a string using $output = (string) $importer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output option for the importer to XML format.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function asXml()
|
||||
{
|
||||
$this->asFormat = 'xml';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all data and options are in order prior to importer.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
abstract public function check();
|
||||
|
||||
/**
|
||||
* Specifies the data source to import.
|
||||
*
|
||||
* @param \SimpleXMLElement|string $from The data source to import, either as a SimpleXMLElement object or XML string.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function from($from)
|
||||
{
|
||||
$this->from = $from;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add a column.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param \SimpleXMLElement $field The XML field definition.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getAddColumnSql($table, \SimpleXMLElement $field)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' ADD COLUMN ' . $this->getColumnSQL($field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alters for table if there is a difference.
|
||||
*
|
||||
* @param \SimpleXMLElement $structure The XML structure of the table.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
abstract protected function getAlterTableSql(\SimpleXMLElement $structure);
|
||||
|
||||
/**
|
||||
* Get the syntax to alter a column.
|
||||
*
|
||||
* @param string $table The name of the database table to alter.
|
||||
* @param \SimpleXMLElement $field The XML definition for the field.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getChangeColumnSql($table, \SimpleXMLElement $field)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' CHANGE COLUMN ' . $this->db->quoteName((string) $field['Field']) . ' '
|
||||
. $this->getColumnSQL($field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax for a single column that would be included in a table create or alter statement.
|
||||
*
|
||||
* @param \SimpleXMLElement $field The XML field definition.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract protected function getColumnSql(\SimpleXMLElement $field);
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a column.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param string $name The name of the field to drop.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getDropColumnSql($table, $name)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP COLUMN ' . $this->db->quoteName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of keys for a table.
|
||||
*
|
||||
* @param array $keys An array of objects that comprise the keys for the table.
|
||||
*
|
||||
* @return array The lookup array. array({key name} => array(object, ...))
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getKeyLookup($keys)
|
||||
{
|
||||
// First pass, create a lookup of the keys.
|
||||
$lookup = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if ($key instanceof \SimpleXMLElement) {
|
||||
$kName = (string) $key['Key_name'];
|
||||
} else {
|
||||
$kName = $key->Key_name;
|
||||
}
|
||||
|
||||
if (empty($lookup[$kName])) {
|
||||
$lookup[$kName] = [];
|
||||
}
|
||||
|
||||
$lookup[$kName][] = $key;
|
||||
}
|
||||
|
||||
return $lookup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the real name of the table, converting the prefix wildcard string if present.
|
||||
*
|
||||
* @param string $table The name of the table.
|
||||
*
|
||||
* @return string The real name of the table.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getRealTableName($table)
|
||||
{
|
||||
$prefix = $this->db->getPrefix();
|
||||
|
||||
// Replace the magic prefix if found.
|
||||
$table = preg_replace('|^#__|', $prefix, $table);
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the data from the source into the existing tables.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @note Currently only supports XML format.
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException on error.
|
||||
*/
|
||||
public function importData()
|
||||
{
|
||||
if ($this->from instanceof \SimpleXMLElement) {
|
||||
$xml = $this->from;
|
||||
} else {
|
||||
$xml = new \SimpleXMLElement($this->from);
|
||||
}
|
||||
|
||||
// Get all the table definitions.
|
||||
$xmlTables = $xml->xpath('database/table_data');
|
||||
|
||||
foreach ($xmlTables as $table) {
|
||||
// Convert the magic prefix into the real table name.
|
||||
$tableName = $this->getRealTableName((string) $table['name']);
|
||||
|
||||
$rows = $table->children();
|
||||
|
||||
foreach ($rows as $row) {
|
||||
if ($row->getName() == 'row') {
|
||||
$entry = new \stdClass();
|
||||
|
||||
foreach ($row->children() as $data) {
|
||||
if (isset($data['value_is_null'])) {
|
||||
$entry->{(string) $data['name']} = null;
|
||||
} else {
|
||||
$entry->{(string) $data['name']} = (string) $data;
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->insertObject($tableName, $entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the incoming structure definition with the existing structure.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @note Currently only supports XML format.
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException on error.
|
||||
*/
|
||||
public function mergeStructure()
|
||||
{
|
||||
$tables = $this->db->getTableList();
|
||||
|
||||
if ($this->from instanceof \SimpleXMLElement) {
|
||||
$xml = $this->from;
|
||||
} else {
|
||||
$xml = new \SimpleXMLElement($this->from);
|
||||
}
|
||||
|
||||
// Get all the table definitions.
|
||||
$xmlTables = $xml->xpath('database/table_structure');
|
||||
|
||||
foreach ($xmlTables as $table) {
|
||||
// Convert the magic prefix into the real table name.
|
||||
$tableName = $this->getRealTableName((string) $table['name']);
|
||||
|
||||
if (\in_array($tableName, $tables, true)) {
|
||||
// The table already exists. Now check if there is any difference.
|
||||
if ($queries = $this->getAlterTableSql($table)) {
|
||||
// Run the queries to upgrade the data structure.
|
||||
foreach ($queries as $query) {
|
||||
$this->db->setQuery((string) $query);
|
||||
$this->db->execute();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This is a new table.
|
||||
$sql = $this->xmlToCreate($table);
|
||||
$queries = explode(';', (string) $sql);
|
||||
|
||||
foreach ($queries as $query) {
|
||||
if (!empty($query)) {
|
||||
$this->db->setQuery((string) $query);
|
||||
$this->db->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database connector to use for exporting structure and/or data.
|
||||
*
|
||||
* @param DatabaseInterface $db The database connector.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function setDbo(DatabaseInterface $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an internal option to merge the structure based on the input data.
|
||||
*
|
||||
* @param boolean $setting True to import the structure, false to not.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function withStructure($setting = true)
|
||||
{
|
||||
$this->options->withStructure = (bool) $setting;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add a table.
|
||||
*
|
||||
* @param \SimpleXMLElement $table The table information.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
abstract protected function xmlToCreate(\SimpleXMLElement $table);
|
||||
}
|
||||
619
libraries/vendor/joomla/database/src/DatabaseInterface.php
vendored
Normal file
619
libraries/vendor/joomla/database/src/DatabaseInterface.php
vendored
Normal file
@ -0,0 +1,619 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Joomla Framework Database Interface
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
interface DatabaseInterface
|
||||
{
|
||||
/**
|
||||
* Connects to the database if needed.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function connect();
|
||||
|
||||
/**
|
||||
* Determines if the connection to the server is active.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function connected();
|
||||
|
||||
/**
|
||||
* Create a new database using information from $options object.
|
||||
*
|
||||
* @param \stdClass $options Object used to pass user and database name to database driver. This object must have "db_name" and "db_user" set.
|
||||
* @param boolean $utf True if the database supports the UTF-8 character set.
|
||||
*
|
||||
* @return boolean|resource
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function createDatabase($options, $utf = true);
|
||||
|
||||
/**
|
||||
* Replace special placeholder representing binary field with the original string.
|
||||
*
|
||||
* @param string|resource $data Encoded string or resource.
|
||||
*
|
||||
* @return string The original string.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function decodeBinary($data);
|
||||
|
||||
/**
|
||||
* Disconnects the database.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function disconnect();
|
||||
|
||||
/**
|
||||
* Drops a table from the database.
|
||||
*
|
||||
* @param string $table The name of the database table to drop.
|
||||
* @param boolean $ifExists Optionally specify that the table must exist before it is dropped.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function dropTable($table, $ifExists = true);
|
||||
|
||||
/**
|
||||
* Escapes a string for usage in an SQL statement.
|
||||
*
|
||||
* @param string $text The string to be escaped.
|
||||
* @param boolean $extra Optional parameter to provide extra escaping.
|
||||
*
|
||||
* @return string The escaped string.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function escape($text, $extra = false);
|
||||
|
||||
/**
|
||||
* Execute the SQL statement.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function execute();
|
||||
|
||||
/**
|
||||
* Get the number of affected rows for the previous executed SQL statement.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getAffectedRows();
|
||||
|
||||
/**
|
||||
* Method to get the database collation in use by sampling a text field of a table in the database.
|
||||
*
|
||||
* @return string|boolean The collation in use by the database or boolean false if not supported.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getCollation();
|
||||
|
||||
/**
|
||||
* Method that provides access to the underlying database connection.
|
||||
*
|
||||
* @return resource The underlying database connection resource.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getConnection();
|
||||
|
||||
/**
|
||||
* Method to get the database connection collation, as reported by the driver.
|
||||
*
|
||||
* If the connector doesn't support reporting this value please return an empty string.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getConnectionCollation();
|
||||
|
||||
/**
|
||||
* Method to get the database encryption details (cipher and protocol) in use.
|
||||
*
|
||||
* @return string The database encryption details.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getConnectionEncryption(): string;
|
||||
|
||||
/**
|
||||
* Method to test if the database TLS connections encryption are supported.
|
||||
*
|
||||
* @return boolean Whether the database supports TLS connections encryption.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function isConnectionEncryptionSupported(): bool;
|
||||
|
||||
/**
|
||||
* Method to check whether the installed database version is supported by the database driver
|
||||
*
|
||||
* @return boolean True if the database version is supported
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function isMinimumVersion();
|
||||
|
||||
/**
|
||||
* Get the total number of SQL statements executed by the database driver.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getCount();
|
||||
|
||||
/**
|
||||
* Returns a PHP date() function compliant date format for the database driver.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getDateFormat();
|
||||
|
||||
/**
|
||||
* Get the minimum supported database version.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getMinimum();
|
||||
|
||||
/**
|
||||
* Get the name of the database driver.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Get the null or zero representation of a timestamp for the database driver.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getNullDate();
|
||||
|
||||
/**
|
||||
* Get the common table prefix for the database driver.
|
||||
*
|
||||
* @return string The common database table prefix.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function getPrefix();
|
||||
|
||||
/**
|
||||
* Get the number of returned rows for the previous executed SQL statement.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getNumRows();
|
||||
|
||||
/**
|
||||
* Get the current query object or a new QueryInterface object.
|
||||
*
|
||||
* @param boolean $new False to return the current query object, True to return a new QueryInterface object.
|
||||
*
|
||||
* @return QueryInterface
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getQuery($new = false);
|
||||
|
||||
/**
|
||||
* Get the server family type.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getServerType();
|
||||
|
||||
/**
|
||||
* Retrieves field information about the given tables.
|
||||
*
|
||||
* @param string $table The name of the database table.
|
||||
* @param boolean $typeOnly True (default) to only return field types.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableColumns($table, $typeOnly = true);
|
||||
|
||||
/**
|
||||
* Retrieves field information about the given tables.
|
||||
*
|
||||
* @param mixed $tables A table name or a list of table names.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableKeys($tables);
|
||||
|
||||
/**
|
||||
* Method to get an array of all tables in the database.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableList();
|
||||
|
||||
/**
|
||||
* Get the version of the database connector.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getVersion();
|
||||
|
||||
/**
|
||||
* Determine whether or not the database engine supports UTF-8 character encoding.
|
||||
*
|
||||
* @return boolean True if the database engine supports UTF-8 character encoding.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function hasUtfSupport();
|
||||
|
||||
/**
|
||||
* Method to get the auto-incremented value from the last INSERT statement.
|
||||
*
|
||||
* @return mixed The value of the auto-increment field from the last inserted row.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function insertid();
|
||||
|
||||
/**
|
||||
* Inserts a row into a table based on an object's properties.
|
||||
*
|
||||
* @param string $table The name of the database table to insert into.
|
||||
* @param object $object A reference to an object whose public properties match the table fields.
|
||||
* @param string $key The name of the primary key. If provided the object property is updated.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function insertObject($table, &$object, $key = null);
|
||||
|
||||
/**
|
||||
* Test to see if the connector is available.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function isSupported();
|
||||
|
||||
/**
|
||||
* Method to get the first row of the result set from the database query as an associative array of ['field_name' => 'row_value'].
|
||||
*
|
||||
* @return mixed The return value or null if the query failed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadAssoc();
|
||||
|
||||
/**
|
||||
* Method to get an array of the result set rows from the database query where each row is an associative array
|
||||
* of ['field_name' => 'row_value']. The array of rows can optionally be keyed by a field name, but defaults to
|
||||
* a sequential numeric array.
|
||||
*
|
||||
* NOTE: Choosing to key the result array by a non-unique field name can result in unwanted
|
||||
* behavior and should be avoided.
|
||||
*
|
||||
* @param string $key The name of a field on which to key the result array.
|
||||
* @param string $column An optional column name. Instead of the whole row, only this column value will be in the result array.
|
||||
*
|
||||
* @return mixed The return value or null if the query failed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadAssocList($key = null, $column = null);
|
||||
|
||||
/**
|
||||
* Method to get an array of values from the <var>$offset</var> field in each row of the result set from the database query.
|
||||
*
|
||||
* @param integer $offset The row offset to use to build the result array.
|
||||
*
|
||||
* @return mixed The return value or null if the query failed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadColumn($offset = 0);
|
||||
|
||||
/**
|
||||
* Method to get the first row of the result set from the database query as an object.
|
||||
*
|
||||
* @param string $class The class name to use for the returned row object.
|
||||
*
|
||||
* @return mixed The return value or null if the query failed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadObject($class = \stdClass::class);
|
||||
|
||||
/**
|
||||
* Method to get an array of the result set rows from the database query where each row is an object. The array
|
||||
* of objects can optionally be keyed by a field name, but defaults to a sequential numeric array.
|
||||
*
|
||||
* NOTE: Choosing to key the result array by a non-unique field name can result in unwanted behavior and should be avoided.
|
||||
*
|
||||
* @param string $key The name of a field on which to key the result array.
|
||||
* @param string $class The class name to use for the returned row objects.
|
||||
*
|
||||
* @return mixed The return value or null if the query failed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadObjectList($key = '', $class = \stdClass::class);
|
||||
|
||||
/**
|
||||
* Method to get the first field of the first row of the result set from the database query.
|
||||
*
|
||||
* @return mixed The return value or null if the query failed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadResult();
|
||||
|
||||
/**
|
||||
* Method to get the first row of the result set from the database query as an array.
|
||||
*
|
||||
* Columns are indexed numerically so the first column in the result set would be accessible via <var>$row[0]</var>, etc.
|
||||
*
|
||||
* @return mixed The return value or null if the query failed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadRow();
|
||||
|
||||
/**
|
||||
* Method to get an array of the result set rows from the database query where each row is an array. The array
|
||||
* of objects can optionally be keyed by a field offset, but defaults to a sequential numeric array.
|
||||
*
|
||||
* NOTE: Choosing to key the result array by a non-unique field can result in unwanted behavior and should be avoided.
|
||||
*
|
||||
* @param string $key The name of a field on which to key the result array.
|
||||
*
|
||||
* @return mixed The return value or null if the query failed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadRowList($key = null);
|
||||
|
||||
/**
|
||||
* Locks a table in the database.
|
||||
*
|
||||
* @param string $tableName The name of the table to unlock.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function lockTable($tableName);
|
||||
|
||||
/**
|
||||
* Quotes and optionally escapes a string to database requirements for use in database queries.
|
||||
*
|
||||
* @param array|string $text A string or an array of strings to quote.
|
||||
* @param boolean $escape True (default) to escape the string, false to leave it unchanged.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function quote($text, $escape = true);
|
||||
|
||||
/**
|
||||
* Quotes a binary string to database requirements for use in database queries.
|
||||
*
|
||||
* @param string $data A binary string to quote.
|
||||
*
|
||||
* @return string The binary quoted input string.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function quoteBinary($data);
|
||||
|
||||
/**
|
||||
* Wrap an SQL statement identifier name such as column, table or database names in quotes to prevent injection
|
||||
* risks and reserved word conflicts.
|
||||
*
|
||||
* @param array|string $name The identifier name to wrap in quotes, or an array of identifier names to wrap in quotes.
|
||||
* Each type supports dot-notation name.
|
||||
* @param array|string $as The AS query part associated to $name. It can be string or array, in latter case it has to be
|
||||
* same length of $name; if is null there will not be any AS part for string or array element.
|
||||
*
|
||||
* @return array|string The quote wrapped name, same type of $name.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function quoteName($name, $as = null);
|
||||
|
||||
/**
|
||||
* Renames a table in the database.
|
||||
*
|
||||
* @param string $oldTable The name of the table to be renamed
|
||||
* @param string $newTable The new name for the table.
|
||||
* @param string $backup Table prefix
|
||||
* @param string $prefix For the table - used to rename constraints in non-mysql databases
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function renameTable($oldTable, $newTable, $backup = null, $prefix = null);
|
||||
|
||||
/**
|
||||
* This function replaces a string identifier with the configured table prefix.
|
||||
*
|
||||
* @param string $sql The SQL statement to prepare.
|
||||
* @param string $prefix The table prefix.
|
||||
*
|
||||
* @return string The processed SQL statement.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function replacePrefix($sql, $prefix = '#__');
|
||||
|
||||
/**
|
||||
* Select a database for use.
|
||||
*
|
||||
* @param string $database The name of the database to select for use.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function select($database);
|
||||
|
||||
/**
|
||||
* Sets the SQL statement string for later execution.
|
||||
*
|
||||
* @param mixed $query The SQL statement to set either as a Query object or a string.
|
||||
* @param integer $offset The affected row offset to set. {@deprecated 3.0 Use LimitableInterface::setLimit() instead}
|
||||
* @param integer $limit The maximum affected rows to set. {@deprecated 3.0 Use LimitableInterface::setLimit() instead}
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function setQuery($query, $offset = 0, $limit = 0);
|
||||
|
||||
/**
|
||||
* Method to commit a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, commit to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionCommit($toSavepoint = false);
|
||||
|
||||
/**
|
||||
* Method to roll back a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, rollback to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionRollback($toSavepoint = false);
|
||||
|
||||
/**
|
||||
* Method to initialize a transaction.
|
||||
*
|
||||
* @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionStart($asSavepoint = false);
|
||||
|
||||
/**
|
||||
* Method to truncate a table.
|
||||
*
|
||||
* @param string $table The table to truncate
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function truncateTable($table);
|
||||
|
||||
/**
|
||||
* Unlocks tables in the database.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function unlockTables();
|
||||
|
||||
/**
|
||||
* Updates a row in a table based on an object's properties.
|
||||
*
|
||||
* @param string $table The name of the database table to update.
|
||||
* @param object $object A reference to an object whose public properties match the table fields.
|
||||
* @param array|string $key The name of the primary key.
|
||||
* @param boolean $nulls True to update null fields or false to ignore them.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function updateObject($table, &$object, $key, $nulls = false);
|
||||
}
|
||||
246
libraries/vendor/joomla/database/src/DatabaseIterator.php
vendored
Normal file
246
libraries/vendor/joomla/database/src/DatabaseIterator.php
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Joomla Framework Database Driver Class
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class DatabaseIterator implements \Countable, \Iterator
|
||||
{
|
||||
/**
|
||||
* The class of object to create.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $class;
|
||||
|
||||
/**
|
||||
* The name of the column to use for the key of the database record.
|
||||
*
|
||||
* @var mixed
|
||||
* @since 1.0
|
||||
*/
|
||||
private $column;
|
||||
|
||||
/**
|
||||
* The current database record.
|
||||
*
|
||||
* @var mixed
|
||||
* @since 1.0
|
||||
*/
|
||||
private $current;
|
||||
|
||||
/**
|
||||
* A numeric or string key for the current database record.
|
||||
*
|
||||
* @var scalar
|
||||
* @since 1.0
|
||||
*/
|
||||
private $key;
|
||||
|
||||
/**
|
||||
* The number of fetched records.
|
||||
*
|
||||
* @var integer
|
||||
* @since 1.0
|
||||
*/
|
||||
private $fetched = 0;
|
||||
|
||||
/**
|
||||
* The statement holding the result set to iterate.
|
||||
*
|
||||
* @var StatementInterface
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $statement;
|
||||
|
||||
/**
|
||||
* Database iterator constructor.
|
||||
*
|
||||
* @param StatementInterface $statement The statement holding the result set to iterate.
|
||||
* @param string $column An option column to use as the iterator key.
|
||||
* @param string $class The class of object that is returned.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(StatementInterface $statement, $column = null, $class = \stdClass::class)
|
||||
{
|
||||
if (!class_exists($class)) {
|
||||
throw new \InvalidArgumentException(sprintf('new %s(*%s*, cursor)', \get_class($this), \gettype($class)));
|
||||
}
|
||||
|
||||
if ($statement) {
|
||||
$fetchMode = $class === \stdClass::class ? FetchMode::STANDARD_OBJECT : FetchMode::CUSTOM_OBJECT;
|
||||
|
||||
// PDO doesn't allow extra arguments for \PDO::FETCH_CLASS, so only forward the class for the custom object mode
|
||||
if ($fetchMode === FetchMode::STANDARD_OBJECT) {
|
||||
$statement->setFetchMode($fetchMode);
|
||||
} else {
|
||||
$statement->setFetchMode($fetchMode, $class);
|
||||
}
|
||||
}
|
||||
|
||||
$this->statement = $statement;
|
||||
$this->class = $class;
|
||||
$this->column = $column;
|
||||
$this->fetched = 0;
|
||||
$this->next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Database iterator destructor.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->statement) {
|
||||
$this->freeResult();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of rows in the result set for the executed SQL given by the cursor.
|
||||
*
|
||||
* @return integer The number of rows in the result set.
|
||||
*
|
||||
* @see Countable::count()
|
||||
* @since 1.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
if ($this->statement) {
|
||||
return $this->statement->rowCount();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current element in the iterator.
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @see Iterator::current()
|
||||
* @since 1.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
return $this->current;
|
||||
}
|
||||
|
||||
/**
|
||||
* The key of the current element in the iterator.
|
||||
*
|
||||
* @return scalar
|
||||
*
|
||||
* @see Iterator::key()
|
||||
* @since 1.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves forward to the next result from the SQL query.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @see Iterator::next()
|
||||
* @since 1.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
// Set the default key as being the number of fetched object
|
||||
$this->key = $this->fetched;
|
||||
|
||||
// Try to get an object
|
||||
$this->current = $this->fetchObject();
|
||||
|
||||
// If an object has been found
|
||||
if ($this->current) {
|
||||
// Set the key as being the indexed column (if it exists)
|
||||
if ($this->column && isset($this->current->{$this->column})) {
|
||||
$this->key = $this->current->{$this->column};
|
||||
}
|
||||
|
||||
// Update the number of fetched object
|
||||
$this->fetched++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewinds the iterator.
|
||||
*
|
||||
* This iterator cannot be rewound.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @see Iterator::rewind()
|
||||
* @since 1.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current position of the iterator is valid.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @see Iterator::valid()
|
||||
* @since 1.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return (bool) $this->current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to fetch a row from the result set cursor as an object.
|
||||
*
|
||||
* @return mixed Either the next row from the result set or false if there are no more rows.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function fetchObject()
|
||||
{
|
||||
if ($this->statement) {
|
||||
return $this->statement->fetch();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to free up the memory used for the result set.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function freeResult()
|
||||
{
|
||||
if ($this->statement) {
|
||||
$this->statement->closeCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
2370
libraries/vendor/joomla/database/src/DatabaseQuery.php
vendored
Normal file
2370
libraries/vendor/joomla/database/src/DatabaseQuery.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
56
libraries/vendor/joomla/database/src/Event/ConnectionEvent.php
vendored
Normal file
56
libraries/vendor/joomla/database/src/Event/ConnectionEvent.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Event;
|
||||
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\Event\Event;
|
||||
|
||||
/**
|
||||
* Database connection event
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class ConnectionEvent extends Event
|
||||
{
|
||||
/**
|
||||
* DatabaseInterface object for this event
|
||||
*
|
||||
* @var DatabaseInterface
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $driver;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The event name.
|
||||
* @param DatabaseInterface $driver The DatabaseInterface object for this event.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __construct(string $name, DatabaseInterface $driver)
|
||||
{
|
||||
parent::__construct($name);
|
||||
|
||||
$this->driver = $driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the DatabaseInterface object attached to this event.
|
||||
*
|
||||
* @return DatabaseInterface
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getDriver(): DatabaseInterface
|
||||
{
|
||||
return $this->driver;
|
||||
}
|
||||
}
|
||||
35
libraries/vendor/joomla/database/src/Exception/ConnectionFailureException.php
vendored
Normal file
35
libraries/vendor/joomla/database/src/Exception/ConnectionFailureException.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Exception;
|
||||
|
||||
/**
|
||||
* Exception class defining an error connecting to the database platform
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class ConnectionFailureException extends \RuntimeException
|
||||
{
|
||||
/**
|
||||
* Construct the exception
|
||||
*
|
||||
* @param string $message The Exception message to throw. [optional]
|
||||
* @param integer $code The Exception code. [optional]
|
||||
* @param ?\Exception $previous The previous exception used for the exception chaining. [optional]
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __construct($message = '', $code = 0, \Exception $previous = null)
|
||||
{
|
||||
// PDO uses strings for exception codes, PHP forces numeric codes, so "force" the string code to be used
|
||||
parent::__construct($message, 0, $previous);
|
||||
|
||||
$this->code = $code;
|
||||
}
|
||||
}
|
||||
19
libraries/vendor/joomla/database/src/Exception/DatabaseNotFoundException.php
vendored
Normal file
19
libraries/vendor/joomla/database/src/Exception/DatabaseNotFoundException.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2022 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Exception;
|
||||
|
||||
/**
|
||||
* No database is available.
|
||||
*
|
||||
* @since 2.1.0
|
||||
*/
|
||||
class DatabaseNotFoundException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
57
libraries/vendor/joomla/database/src/Exception/ExecutionFailureException.php
vendored
Normal file
57
libraries/vendor/joomla/database/src/Exception/ExecutionFailureException.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Exception;
|
||||
|
||||
/**
|
||||
* Exception class defining an error executing a statement
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class ExecutionFailureException extends \RuntimeException
|
||||
{
|
||||
/**
|
||||
* The SQL statement that was executed.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.5.0
|
||||
*/
|
||||
private $query;
|
||||
|
||||
/**
|
||||
* Construct the exception
|
||||
*
|
||||
* @param string $query The SQL statement that was executed.
|
||||
* @param string $message The Exception message to throw. [optional]
|
||||
* @param integer $code The Exception code. [optional]
|
||||
* @param ?\Exception $previous The previous exception used for the exception chaining. [optional]
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public function __construct($query, $message = '', $code = 0, \Exception $previous = null)
|
||||
{
|
||||
// PDO uses strings for exception codes, PHP forces numeric codes, so "force" the string code to be used
|
||||
parent::__construct($message, 0, $previous);
|
||||
|
||||
$this->code = $code;
|
||||
$this->query = $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL statement that was executed
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public function getQuery()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
}
|
||||
35
libraries/vendor/joomla/database/src/Exception/PrepareStatementFailureException.php
vendored
Normal file
35
libraries/vendor/joomla/database/src/Exception/PrepareStatementFailureException.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Exception;
|
||||
|
||||
/**
|
||||
* Exception class defining an error preparing the SQL statement for execution
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class PrepareStatementFailureException extends \RuntimeException
|
||||
{
|
||||
/**
|
||||
* Construct the exception
|
||||
*
|
||||
* @param string $message The Exception message to throw. [optional]
|
||||
* @param integer $code The Exception code. [optional]
|
||||
* @param ?\Exception $previous The previous exception used for the exception chaining. [optional]
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __construct($message = '', $code = 0, \Exception $previous = null)
|
||||
{
|
||||
// PDO uses strings for exception codes, PHP forces numeric codes, so "force" the string code to be used
|
||||
parent::__construct($message, 0, $previous);
|
||||
|
||||
$this->code = $code;
|
||||
}
|
||||
}
|
||||
19
libraries/vendor/joomla/database/src/Exception/QueryTypeAlreadyDefinedException.php
vendored
Normal file
19
libraries/vendor/joomla/database/src/Exception/QueryTypeAlreadyDefinedException.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Exception;
|
||||
|
||||
/**
|
||||
* Exception class defining an exception when attempting to change a query type
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class QueryTypeAlreadyDefinedException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
19
libraries/vendor/joomla/database/src/Exception/UnknownTypeException.php
vendored
Normal file
19
libraries/vendor/joomla/database/src/Exception/UnknownTypeException.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Exception;
|
||||
|
||||
/**
|
||||
* Class representing an unknown type for a given database driver.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class UnknownTypeException extends \InvalidArgumentException
|
||||
{
|
||||
}
|
||||
19
libraries/vendor/joomla/database/src/Exception/UnsupportedAdapterException.php
vendored
Normal file
19
libraries/vendor/joomla/database/src/Exception/UnsupportedAdapterException.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Exception;
|
||||
|
||||
/**
|
||||
* Exception class defining an unsupported database object
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class UnsupportedAdapterException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
88
libraries/vendor/joomla/database/src/FetchMode.php
vendored
Normal file
88
libraries/vendor/joomla/database/src/FetchMode.php
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Class defining the fetch mode for prepared statements
|
||||
*
|
||||
* The values of the constants in this class match the `PDO::FETCH_*` constants.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
final class FetchMode
|
||||
{
|
||||
/**
|
||||
* Specifies that the fetch method shall return each row as an array indexed by column name as returned in the corresponding result set.
|
||||
*
|
||||
* If the result set contains multiple columns with the same name, the statement returns only a single value per column name.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
* @see \PDO::FETCH_ASSOC
|
||||
*/
|
||||
public const ASSOCIATIVE = 2;
|
||||
|
||||
/**
|
||||
* Specifies that the fetch method shall return each row as an array indexed by column number as returned in the corresponding result set,
|
||||
* starting at column 0.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
* @see \PDO::FETCH_NUM
|
||||
*/
|
||||
public const NUMERIC = 3;
|
||||
|
||||
/**
|
||||
* Specifies that the fetch method shall return each row as an array indexed by both column name and number as returned in the corresponding
|
||||
* result set, starting at column 0.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
* @see \PDO::FETCH_BOTH
|
||||
*/
|
||||
public const MIXED = 4;
|
||||
|
||||
/**
|
||||
* Specifies that the fetch method shall return each row as an object with property names that correspond to the column names returned in the
|
||||
* result set.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
* @see \PDO::FETCH_OBJ
|
||||
*/
|
||||
public const STANDARD_OBJECT = 5;
|
||||
|
||||
/**
|
||||
* Specifies that the fetch method shall return only a single requested column from the next row in the result set.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
* @see \PDO::FETCH_COLUMN
|
||||
*/
|
||||
public const COLUMN = 7;
|
||||
|
||||
/**
|
||||
* Specifies that the fetch method shall return a new instance of the requested class, mapping the columns to named properties in the class.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
* @see \PDO::FETCH_CLASS
|
||||
*/
|
||||
public const CUSTOM_OBJECT = 8;
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation of this class
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
77
libraries/vendor/joomla/database/src/FetchOrientation.php
vendored
Normal file
77
libraries/vendor/joomla/database/src/FetchOrientation.php
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Class defining the fetch orientation for prepared statements
|
||||
*
|
||||
* The values of the constants in this class match the `PDO::FETCH_ORI_*` constants.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
final class FetchOrientation
|
||||
{
|
||||
/**
|
||||
* Fetch the next row in the result set. Valid only for scrollable cursors.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const NEXT = 0;
|
||||
|
||||
/**
|
||||
* Fetch the previous row in the result set. Valid only for scrollable cursors.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const PRIOR = 1;
|
||||
|
||||
/**
|
||||
* Fetch the first row in the result set. Valid only for scrollable cursors.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const FIRST = 2;
|
||||
|
||||
/**
|
||||
* Fetch the last row in the result set. Valid only for scrollable cursors.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const LAST = 3;
|
||||
|
||||
/**
|
||||
* Fetch the requested row by row number from the result set. Valid only for scrollable cursors.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const ABS = 4;
|
||||
|
||||
/**
|
||||
* Fetch the requested row by relative position from the current position of the cursor in the result set. Valid only for scrollable cursors.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const REL = 5;
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation of this class
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
74
libraries/vendor/joomla/database/src/Monitor/ChainedMonitor.php
vendored
Normal file
74
libraries/vendor/joomla/database/src/Monitor/ChainedMonitor.php
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Monitor;
|
||||
|
||||
use Joomla\Database\QueryMonitorInterface;
|
||||
|
||||
/**
|
||||
* Chained query monitor allowing multiple monitors to be executed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class ChainedMonitor implements QueryMonitorInterface
|
||||
{
|
||||
/**
|
||||
* The query monitors stored to this chain
|
||||
*
|
||||
* @var QueryMonitorInterface[]
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $monitors = [];
|
||||
|
||||
/**
|
||||
* Register a monitor to the chain.
|
||||
*
|
||||
* @param QueryMonitorInterface $monitor The monitor to add.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function addMonitor(QueryMonitorInterface $monitor): void
|
||||
{
|
||||
$this->monitors[] = $monitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Act on a query being started.
|
||||
*
|
||||
* @param string $sql The SQL to be executed.
|
||||
* @param object[]|null $boundParams List of bound params, used with the query.
|
||||
* Each item is an object that holds: value, dataType
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function startQuery(string $sql, ?array $boundParams = null): void
|
||||
{
|
||||
foreach ($this->monitors as $monitor) {
|
||||
$monitor->startQuery($sql, $boundParams);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Act on a query being stopped.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function stopQuery(): void
|
||||
{
|
||||
foreach ($this->monitors as $monitor) {
|
||||
$monitor->stopQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
156
libraries/vendor/joomla/database/src/Monitor/DebugMonitor.php
vendored
Normal file
156
libraries/vendor/joomla/database/src/Monitor/DebugMonitor.php
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Monitor;
|
||||
|
||||
use Joomla\Database\QueryMonitorInterface;
|
||||
|
||||
/**
|
||||
* Query monitor handling logging of queries.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
final class DebugMonitor implements QueryMonitorInterface
|
||||
{
|
||||
/**
|
||||
* The log of executed SQL statements call stacks by the database driver.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $callStacks = [];
|
||||
|
||||
/**
|
||||
* The log of executed SQL statements by the database driver.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $logs = [];
|
||||
|
||||
/**
|
||||
* List of bound params, used with the query.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $boundParams = [];
|
||||
|
||||
/**
|
||||
* The log of executed SQL statements memory usage (start and stop memory_get_usage) by the database driver.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $memoryLogs = [];
|
||||
|
||||
/**
|
||||
* The log of executed SQL statements timings (start and stop microtimes) by the database driver.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $timings = [];
|
||||
|
||||
/**
|
||||
* Act on a query being started.
|
||||
*
|
||||
* @param string $sql The SQL to be executed.
|
||||
* @param object[]|null $boundParams List of bound params, used with the query.
|
||||
* Each item is an object that holds: value, dataType
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function startQuery(string $sql, ?array $boundParams = null): void
|
||||
{
|
||||
$this->logs[] = $sql;
|
||||
|
||||
// Dereference bound parameters to prevent reporting wrong value when reusing the same query object.
|
||||
$this->boundParams[] = unserialize(serialize($boundParams));
|
||||
|
||||
$this->callStacks[] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
$this->memoryLogs[] = memory_get_usage();
|
||||
$this->timings[] = microtime(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Act on a query being stopped.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function stopQuery(): void
|
||||
{
|
||||
$this->timings[] = microtime(true);
|
||||
$this->memoryLogs[] = memory_get_usage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logged call stacks.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getCallStacks(): array
|
||||
{
|
||||
return $this->callStacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logged queries.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getLogs(): array
|
||||
{
|
||||
return $this->logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logged bound params.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getBoundParams(): array
|
||||
{
|
||||
return $this->boundParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logged memory logs.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getMemoryLogs(): array
|
||||
{
|
||||
return $this->memoryLogs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logged timings.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getTimings(): array
|
||||
{
|
||||
return $this->timings;
|
||||
}
|
||||
}
|
||||
57
libraries/vendor/joomla/database/src/Monitor/LoggingMonitor.php
vendored
Normal file
57
libraries/vendor/joomla/database/src/Monitor/LoggingMonitor.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Monitor;
|
||||
|
||||
use Joomla\Database\QueryMonitorInterface;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* Query monitor handling logging of queries.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class LoggingMonitor implements QueryMonitorInterface, LoggerAwareInterface
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* Act on a query being started.
|
||||
*
|
||||
* @param string $sql The SQL to be executed.
|
||||
* @param object[]|null $boundParams List of bound params, used with the query.
|
||||
* Each item is an object that holds: value, dataType
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function startQuery(string $sql, ?array $boundParams = null): void
|
||||
{
|
||||
if ($this->logger) {
|
||||
// Add the query to the object queue.
|
||||
$this->logger->info(
|
||||
'Query Executed: {sql}',
|
||||
['sql' => $sql, 'trace' => debug_backtrace()]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Act on a query being stopped.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function stopQuery(): void
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
807
libraries/vendor/joomla/database/src/Mysql/MysqlDriver.php
vendored
Normal file
807
libraries/vendor/joomla/database/src/Mysql/MysqlDriver.php
vendored
Normal file
@ -0,0 +1,807 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Mysql;
|
||||
|
||||
use Joomla\Database\Exception\ConnectionFailureException;
|
||||
use Joomla\Database\Pdo\PdoDriver;
|
||||
use Joomla\Database\UTF8MB4SupportInterface;
|
||||
|
||||
/**
|
||||
* MySQL database driver supporting PDO based connections
|
||||
*
|
||||
* @link https://www.php.net/manual/en/ref.pdo-mysql.php
|
||||
* @since 1.0
|
||||
*/
|
||||
class MysqlDriver extends PdoDriver implements UTF8MB4SupportInterface
|
||||
{
|
||||
/**
|
||||
* The name of the database driver.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public $name = 'mysql';
|
||||
|
||||
/**
|
||||
* The character(s) used to quote SQL statement names such as table names or field names, etc.
|
||||
*
|
||||
* If a single character string the same character is used for both sides of the quoted name, else the first character will be used for the
|
||||
* opening quote and the second for the closing quote.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $nameQuote = '`';
|
||||
|
||||
/**
|
||||
* The null or zero representation of a timestamp for the database driver.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $nullDate = '0000-00-00 00:00:00';
|
||||
|
||||
/**
|
||||
* True if the database engine supports UTF-8 Multibyte (utf8mb4) character encoding.
|
||||
*
|
||||
* @var boolean
|
||||
* @since 1.4.0
|
||||
*/
|
||||
protected $utf8mb4 = false;
|
||||
|
||||
/**
|
||||
* True if the database engine is MariaDB.
|
||||
*
|
||||
* @var boolean
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $mariadb = false;
|
||||
|
||||
/**
|
||||
* The minimum supported database version.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected static $dbMinimum = '5.6';
|
||||
|
||||
/**
|
||||
* The minimum supported MariaDB database version.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected static $dbMinMariadb = '10.0';
|
||||
|
||||
/**
|
||||
* The default cipher suite for TLS connections.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected static $defaultCipherSuite = [
|
||||
'AES128-GCM-SHA256',
|
||||
'AES256-GCM-SHA384',
|
||||
'AES128-CBC-SHA256',
|
||||
'AES256-CBC-SHA384',
|
||||
'DES-CBC3-SHA',
|
||||
];
|
||||
|
||||
/**
|
||||
* The default charset.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public $charset = 'utf8';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $options Array of database options with keys: host, user, password, database, select.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __construct(array $options)
|
||||
{
|
||||
/**
|
||||
* sql_mode to MySql 5.7.8+ default strict mode minus ONLY_FULL_GROUP_BY
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-8.html#mysqld-5-7-8-sql-mode
|
||||
*/
|
||||
$sqlModes = [
|
||||
'STRICT_TRANS_TABLES',
|
||||
'ERROR_FOR_DIVISION_BY_ZERO',
|
||||
'NO_ENGINE_SUBSTITUTION',
|
||||
];
|
||||
|
||||
// Get some basic values from the options.
|
||||
$options['driver'] = 'mysql';
|
||||
$options['charset'] = $options['charset'] ?? 'utf8';
|
||||
$options['sqlModes'] = isset($options['sqlModes']) ? (array) $options['sqlModes'] : $sqlModes;
|
||||
|
||||
$this->charset = $options['charset'];
|
||||
|
||||
/*
|
||||
* Pre-populate the UTF-8 Multibyte compatibility flag. Unfortunately PDO won't report the server version unless we're connected to it,
|
||||
* and we cannot connect to it unless we know if it supports utf8mb4, which requires us knowing the server version. Because of this
|
||||
* chicken and egg issue, we _assume_ it's supported and we'll just catch any problems at connection time.
|
||||
*/
|
||||
$this->utf8mb4 = $options['charset'] === 'utf8mb4';
|
||||
|
||||
// Finalize initialisation.
|
||||
parent::__construct($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the database if needed.
|
||||
*
|
||||
* @return void Returns void if the database connected successfully.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
if ($this->getConnection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For SSL/TLS connection encryption.
|
||||
if ($this->options['ssl'] !== [] && $this->options['ssl']['enable'] === true) {
|
||||
$sslContextIsNull = true;
|
||||
|
||||
// If customised, add cipher suite, ca file path, ca path, private key file path and certificate file path to PDO driver options.
|
||||
foreach (['cipher', 'ca', 'capath', 'key', 'cert'] as $key => $value) {
|
||||
if ($this->options['ssl'][$value] !== null) {
|
||||
$this->options['driverOptions'][constant('\PDO::MYSQL_ATTR_SSL_' . strtoupper($value))] = $this->options['ssl'][$value];
|
||||
$sslContextIsNull = false;
|
||||
}
|
||||
}
|
||||
|
||||
// PDO, if no cipher, ca, capath, cert and key are set, can't start TLS one-way connection, set a common ciphers suite to force it.
|
||||
if ($sslContextIsNull === true) {
|
||||
$this->options['driverOptions'][\PDO::MYSQL_ATTR_SSL_CIPHER] = implode(':', static::$defaultCipherSuite);
|
||||
}
|
||||
|
||||
// If customised, for capable systems (PHP 7.0.14+ and 7.1.4+) verify certificate chain and Common Name to driver options.
|
||||
if ($this->options['ssl']['verify_server_cert'] !== null && defined('\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')) {
|
||||
$this->options['driverOptions'][\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $this->options['ssl']['verify_server_cert'];
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Try to connect to MySQL
|
||||
parent::connect();
|
||||
} catch (ConnectionFailureException $e) {
|
||||
// If the connection failed, but not because of the wrong character set, then bubble up the exception.
|
||||
if (!$this->utf8mb4) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, try connecting again without using utf8mb4 and see if maybe that was the problem. If the connection succeeds, then we
|
||||
* will have learned that the client end of the connection does not support utf8mb4.
|
||||
*/
|
||||
$this->utf8mb4 = false;
|
||||
$this->options['charset'] = 'utf8';
|
||||
|
||||
parent::connect();
|
||||
}
|
||||
|
||||
$serverVersion = $this->getVersion();
|
||||
|
||||
$this->mariadb = stripos($serverVersion, 'mariadb') !== false;
|
||||
|
||||
if ($this->utf8mb4) {
|
||||
// At this point we know the client supports utf8mb4. Now we must check if the server supports utf8mb4 as well.
|
||||
$this->utf8mb4 = version_compare($serverVersion, '5.5.3', '>=');
|
||||
|
||||
if ($this->mariadb && version_compare($serverVersion, '10.0.0', '<')) {
|
||||
$this->utf8mb4 = false;
|
||||
}
|
||||
|
||||
if (!$this->utf8mb4) {
|
||||
// Reconnect with the utf8 character set.
|
||||
parent::disconnect();
|
||||
$this->options['charset'] = 'utf8';
|
||||
parent::connect();
|
||||
}
|
||||
}
|
||||
|
||||
// If needed, set the sql modes.
|
||||
if ($this->options['sqlModes'] !== []) {
|
||||
$this->connection->query('SET @@SESSION.sql_mode = \'' . implode(',', $this->options['sqlModes']) . '\';');
|
||||
}
|
||||
|
||||
$this->setOption(\PDO::ATTR_EMULATE_PREPARES, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically downgrade a CREATE TABLE or ALTER TABLE query from utf8mb4 (UTF-8 Multibyte) to plain utf8.
|
||||
*
|
||||
* Used when the server doesn't support UTF-8 Multibyte.
|
||||
*
|
||||
* @param string $query The query to convert
|
||||
*
|
||||
* @return string The converted query
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public function convertUtf8mb4QueryToUtf8($query)
|
||||
{
|
||||
if ($this->hasUTF8mb4Support()) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
// If it's not an ALTER TABLE or CREATE TABLE command there's nothing to convert
|
||||
$beginningOfQuery = substr($query, 0, 12);
|
||||
$beginningOfQuery = strtoupper($beginningOfQuery);
|
||||
|
||||
if (!\in_array($beginningOfQuery, ['ALTER TABLE ', 'CREATE TABLE'], true)) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
// Replace utf8mb4 with utf8
|
||||
return str_replace('utf8mb4', 'utf8', $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the MySQL connector is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
return class_exists('\\PDO') && \in_array('mysql', \PDO::getAvailableDrivers(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a database for use.
|
||||
*
|
||||
* @param string $database The name of the database to select for use.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function select($database)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$this->setQuery('USE ' . $this->quoteName($database))
|
||||
->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query string to alter the database character set.
|
||||
*
|
||||
* @param string $dbName The database name
|
||||
*
|
||||
* @return string The query that alter the database query string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getAlterDbCharacterSet($dbName)
|
||||
{
|
||||
$charset = $this->utf8mb4 ? 'utf8mb4' : 'utf8';
|
||||
|
||||
return 'ALTER DATABASE ' . $this->quoteName($dbName) . ' CHARACTER SET `' . $charset . '`';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database collation in use by sampling a text field of a table in the database.
|
||||
*
|
||||
* @return string|boolean The collation in use by the database (string) or boolean false if not supported.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getCollation()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return $this->setQuery('SELECT @@collation_database;')->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database connection collation in use by sampling a text field of a table in the database.
|
||||
*
|
||||
* @return string|boolean The collation in use by the database connection (string) or boolean false if not supported.
|
||||
*
|
||||
* @since 1.6.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getConnectionCollation()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return $this->setQuery('SELECT @@collation_connection;')->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database encryption details (cipher and protocol) in use.
|
||||
*
|
||||
* @return string The database encryption details.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getConnectionEncryption(): string
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$variables = $this->setQuery('SHOW SESSION STATUS WHERE `Variable_name` IN (\'Ssl_version\', \'Ssl_cipher\')')
|
||||
->loadObjectList('Variable_name');
|
||||
|
||||
if (!empty($variables['Ssl_cipher']->Value)) {
|
||||
return $variables['Ssl_version']->Value . ' (' . $variables['Ssl_cipher']->Value . ')';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test if the database TLS connections encryption are supported.
|
||||
*
|
||||
* @return boolean Whether the database supports TLS connections encryption.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function isConnectionEncryptionSupported(): bool
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$variables = $this->setQuery('SHOW SESSION VARIABLES WHERE `Variable_name` IN (\'have_ssl\')')->loadObjectList('Variable_name');
|
||||
|
||||
return !empty($variables['have_ssl']->Value) && $variables['have_ssl']->Value === 'YES';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query string to create new Database.
|
||||
*
|
||||
* @param \stdClass $options Object used to pass user and database name to database driver. This object must have "db_name" and "db_user" set.
|
||||
* @param boolean $utf True if the database supports the UTF-8 character set.
|
||||
*
|
||||
* @return string The query that creates database
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected function getCreateDatabaseQuery($options, $utf)
|
||||
{
|
||||
if ($utf) {
|
||||
$charset = $this->utf8mb4 ? 'utf8mb4' : 'utf8';
|
||||
$collation = $charset . '_unicode_ci';
|
||||
|
||||
return 'CREATE DATABASE ' . $this->quoteName($options->db_name) . ' CHARACTER SET `' . $charset . '` COLLATE `' . $collation . '`';
|
||||
}
|
||||
|
||||
return 'CREATE DATABASE ' . $this->quoteName($options->db_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the table CREATE statement that creates the given tables.
|
||||
*
|
||||
* @param array|string $tables A table name or a list of table names.
|
||||
*
|
||||
* @return array A list of the create SQL for the tables.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableCreate($tables)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Initialise variables.
|
||||
$result = [];
|
||||
|
||||
// Sanitize input to an array and iterate over the list.
|
||||
$tables = (array) $tables;
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$row = $this->setQuery('SHOW CREATE TABLE ' . $this->quoteName($table))->loadRow();
|
||||
|
||||
// Populate the result array based on the create statements.
|
||||
$result[$table] = $row[1];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves field information about a given table.
|
||||
*
|
||||
* @param string $table The name of the database table.
|
||||
* @param boolean $typeOnly True to only return field types.
|
||||
*
|
||||
* @return array An array of fields for the database table.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableColumns($table, $typeOnly = true)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$result = [];
|
||||
|
||||
// Set the query to get the table fields statement.
|
||||
$fields = $this->setQuery('SHOW FULL COLUMNS FROM ' . $this->quoteName($table))->loadObjectList();
|
||||
|
||||
// If we only want the type as the value add just that to the list.
|
||||
if ($typeOnly) {
|
||||
foreach ($fields as $field) {
|
||||
$result[$field->Field] = preg_replace('/[(0-9)]/', '', $field->Type);
|
||||
}
|
||||
} else {
|
||||
// If we want the whole field data object add that to the list.
|
||||
foreach ($fields as $field) {
|
||||
$result[$field->Field] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of keys for a table.
|
||||
*
|
||||
* @param string $table The name of the table.
|
||||
*
|
||||
* @return array An array of the column specification for the table.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableKeys($table)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Get the details columns information.
|
||||
return $this->setQuery('SHOW KEYS FROM ' . $this->quoteName($table))->loadObjectList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of all tables in the database.
|
||||
*
|
||||
* @return array An array of all the tables in the database.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableList()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Set the query to get the tables statement.
|
||||
return $this->setQuery('SHOW TABLES')->loadColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the database connector.
|
||||
*
|
||||
* @return string The database connector version.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$version = $this->getOption(\PDO::ATTR_SERVER_VERSION);
|
||||
|
||||
if (stripos($version, 'mariadb') !== false) {
|
||||
// MariaDB: Strip off any leading '5.5.5-', if present
|
||||
return preg_replace('/^5\.5\.5-/', '', $version);
|
||||
}
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum supported database version.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getMinimum()
|
||||
{
|
||||
return $this->mariadb ? static::$dbMinMariadb : static::$dbMinimum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the null or zero representation of a timestamp for the database driver.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getNullDate()
|
||||
{
|
||||
// Check the session sql mode;
|
||||
if (\in_array('NO_ZERO_DATE', $this->options['sqlModes']) !== false) {
|
||||
$this->nullDate = '1000-01-01 00:00:00';
|
||||
}
|
||||
|
||||
return $this->nullDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the database engine support the UTF-8 Multibyte (utf8mb4) character encoding.
|
||||
*
|
||||
* @return boolean True if the database engine supports UTF-8 Multibyte.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function hasUTF8mb4Support()
|
||||
{
|
||||
return $this->utf8mb4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the database engine is MariaDB.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function isMariaDb(): bool
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return $this->mariadb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks a table in the database.
|
||||
*
|
||||
* @param string $table The name of the table to unlock.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function lockTable($table)
|
||||
{
|
||||
$this->setQuery('LOCK TABLES ' . $this->quoteName($table) . ' WRITE')
|
||||
->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a table in the database.
|
||||
*
|
||||
* @param string $oldTable The name of the table to be renamed
|
||||
* @param string $newTable The new name for the table.
|
||||
* @param string $backup Not used by MySQL.
|
||||
* @param string $prefix Not used by MySQL.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
|
||||
{
|
||||
$this->setQuery('RENAME TABLE ' . $this->quoteName($oldTable) . ' TO ' . $this->quoteName($newTable))
|
||||
->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a row into a table based on an object's properties.
|
||||
*
|
||||
* @param string $table The name of the database table to insert into.
|
||||
* @param object $object A reference to an object whose public properties match the table fields.
|
||||
* @param string $key The name of the primary key. If provided the object property is updated.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function insertObject($table, &$object, $key = null)
|
||||
{
|
||||
$fields = [];
|
||||
$values = [];
|
||||
$tableColumns = $this->getTableColumns($table);
|
||||
|
||||
// Iterate over the object variables to build the query fields and values.
|
||||
foreach (get_object_vars($object) as $k => $v) {
|
||||
// Skip columns that don't exist in the table.
|
||||
if (!array_key_exists($k, $tableColumns)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only process non-null scalars.
|
||||
if (\is_array($v) || \is_object($v) || $v === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore any internal fields.
|
||||
if ($k[0] === '_') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore null datetime fields.
|
||||
if ($tableColumns[$k] === 'datetime' && empty($v)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore null integer fields.
|
||||
if (stristr($tableColumns[$k], 'int') !== false && $v === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prepare and sanitize the fields and values for the database query.
|
||||
$fields[] = $this->quoteName($k);
|
||||
$values[] = $this->quote($v);
|
||||
}
|
||||
|
||||
// Create the base insert statement.
|
||||
$query = $this->createQuery()
|
||||
->insert($this->quoteName($table))
|
||||
->columns($fields)
|
||||
->values(implode(',', $values));
|
||||
|
||||
// Set the query and execute the insert.
|
||||
$this->setQuery($query)->execute();
|
||||
|
||||
// Update the primary key if it exists.
|
||||
$id = $this->insertid();
|
||||
|
||||
if ($key && $id && \is_string($key)) {
|
||||
$object->$key = $id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to escape a string for usage in an SQL statement.
|
||||
*
|
||||
* Oracle escaping reference:
|
||||
* http://www.orafaq.com/wiki/SQL_FAQ#How_does_one_escape_special_characters_when_writing_SQL_queries.3F
|
||||
*
|
||||
* SQLite escaping notes:
|
||||
* http://www.sqlite.org/faq.html#q14
|
||||
*
|
||||
* Method body is as implemented by the Zend Framework
|
||||
*
|
||||
* Note: Using query objects with bound variables is preferable to the below.
|
||||
*
|
||||
* @param string $text The string to be escaped.
|
||||
* @param boolean $extra Unused optional parameter to provide extra escaping.
|
||||
*
|
||||
* @return string The escaped string.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function escape($text, $extra = false)
|
||||
{
|
||||
if (\is_int($text)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
if (\is_float($text)) {
|
||||
// Force the dot as a decimal point.
|
||||
return str_replace(',', '.', (string) $text);
|
||||
}
|
||||
|
||||
$this->connect();
|
||||
|
||||
$result = substr($this->connection->quote($text), 1, -1);
|
||||
|
||||
if ($extra) {
|
||||
$result = addcslashes($result, '%_');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks tables in the database.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function unlockTables()
|
||||
{
|
||||
$this->setQuery('UNLOCK TABLES')
|
||||
->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to commit a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, commit to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionCommit($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth <= 1) {
|
||||
parent::transactionCommit($toSavepoint);
|
||||
} else {
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to roll back a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, rollback to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionRollback($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth <= 1) {
|
||||
parent::transactionRollback($toSavepoint);
|
||||
} else {
|
||||
$savepoint = 'SP_' . ($this->transactionDepth - 1);
|
||||
$this->setQuery('ROLLBACK TO SAVEPOINT ' . $this->quoteName($savepoint));
|
||||
|
||||
if ($this->execute()) {
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to initialize a transaction.
|
||||
*
|
||||
* @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionStart($asSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$asSavepoint || !$this->transactionDepth) {
|
||||
parent::transactionStart($asSavepoint);
|
||||
} else {
|
||||
$savepoint = 'SP_' . $this->transactionDepth;
|
||||
$this->setQuery('SAVEPOINT ' . $this->quoteName($savepoint));
|
||||
|
||||
if ($this->execute()) {
|
||||
$this->transactionDepth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
libraries/vendor/joomla/database/src/Mysql/MysqlExporter.php
vendored
Normal file
116
libraries/vendor/joomla/database/src/Mysql/MysqlExporter.php
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Mysql;
|
||||
|
||||
use Joomla\Database\DatabaseExporter;
|
||||
|
||||
/**
|
||||
* MySQL Database Exporter.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class MysqlExporter extends DatabaseExporter
|
||||
{
|
||||
/**
|
||||
* Builds the XML data for the tables to export.
|
||||
*
|
||||
* @return string An XML string
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXml()
|
||||
{
|
||||
$buffer = [];
|
||||
|
||||
$buffer[] = '<?xml version="1.0"?>';
|
||||
$buffer[] = '<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
|
||||
$buffer[] = ' <database name="">';
|
||||
|
||||
if ($this->options->withStructure) {
|
||||
$buffer = array_merge($buffer, $this->buildXmlStructure());
|
||||
}
|
||||
|
||||
if ($this->options->withData) {
|
||||
$buffer = array_merge($buffer, $this->buildXmlData());
|
||||
}
|
||||
|
||||
$buffer[] = ' </database>';
|
||||
$buffer[] = '</mysqldump>';
|
||||
|
||||
return implode("\n", $buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XML structure to export.
|
||||
*
|
||||
* @return array An array of XML lines (strings).
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXmlStructure()
|
||||
{
|
||||
$buffer = [];
|
||||
|
||||
foreach ($this->from as $table) {
|
||||
// Replace the magic prefix if found.
|
||||
$table = $this->getGenericTableName($table);
|
||||
|
||||
// Get the details columns information.
|
||||
$fields = $this->db->getTableColumns($table, false);
|
||||
$keys = $this->db->getTableKeys($table);
|
||||
|
||||
$buffer[] = ' <table_structure name="' . $table . '">';
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$buffer[] = ' <field Field="' . $field->Field . '" Type="' . $field->Type . '" Null="' . $field->Null . '" Key="' .
|
||||
$field->Key . '"' . (isset($field->Default) ? ' Default="' . $field->Default . '"' : '') . ' Extra="' . $field->Extra . '"' .
|
||||
' />';
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$buffer[] = ' <key Table="' . $table . '" Non_unique="' . $key->Non_unique . '" Key_name="' . $key->Key_name . '"' .
|
||||
' Seq_in_index="' . $key->Seq_in_index . '" Column_name="' . $key->Column_name . '" Collation="' . $key->Collation . '"' .
|
||||
' Null="' . $key->Null . '" Index_type="' . $key->Index_type . '"' .
|
||||
' Sub_part="' . $key->Sub_part . '"' .
|
||||
' Comment="' . htmlspecialchars($key->Comment, \ENT_COMPAT, 'UTF-8') . '"' .
|
||||
' />';
|
||||
}
|
||||
|
||||
$buffer[] = ' </table_structure>';
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all data and options are in order prior to exporting.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
// Check if the db connector has been set.
|
||||
if (!($this->db instanceof MysqlDriver)) {
|
||||
throw new \RuntimeException('Database connection wrong type.');
|
||||
}
|
||||
|
||||
// Check if the tables have been specified.
|
||||
if (empty($this->from)) {
|
||||
throw new \RuntimeException('ERROR: No Tables Specified');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
398
libraries/vendor/joomla/database/src/Mysql/MysqlImporter.php
vendored
Normal file
398
libraries/vendor/joomla/database/src/Mysql/MysqlImporter.php
vendored
Normal file
@ -0,0 +1,398 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Mysql;
|
||||
|
||||
use Joomla\Database\DatabaseImporter;
|
||||
|
||||
/**
|
||||
* MySQL Database Importer.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class MysqlImporter extends DatabaseImporter
|
||||
{
|
||||
/**
|
||||
* Checks if all data and options are in order prior to exporting.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
// Check if the db connector has been set.
|
||||
if (!($this->db instanceof MysqlDriver)) {
|
||||
throw new \RuntimeException('Database connection wrong type.');
|
||||
}
|
||||
|
||||
// Check if the tables have been specified.
|
||||
if (empty($this->from)) {
|
||||
throw new \RuntimeException('ERROR: No Tables Specified');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param array $keys An array of the fields pertaining to this key.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getAddKeySql($table, $keys)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' ADD ' . $this->getKeySql($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alters for table if there is a difference.
|
||||
*
|
||||
* @param \SimpleXMLElement $structure The XML structure of the table.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getAlterTableSql(\SimpleXMLElement $structure)
|
||||
{
|
||||
// Initialise variables.
|
||||
$table = $this->getRealTableName($structure['name']);
|
||||
$oldFields = $this->db->getTableColumns($table);
|
||||
$oldKeys = $this->db->getTableKeys($table);
|
||||
$alters = [];
|
||||
|
||||
// Get the fields and keys from the XML that we are aiming for.
|
||||
$newFields = $structure->xpath('field');
|
||||
$newKeys = $structure->xpath('key');
|
||||
|
||||
// Loop through each field in the new structure.
|
||||
foreach ($newFields as $field) {
|
||||
$fName = (string) $field['Field'];
|
||||
|
||||
if (isset($oldFields[$fName])) {
|
||||
// The field exists, check it's the same.
|
||||
$column = $oldFields[$fName];
|
||||
|
||||
// Test whether there is a change.
|
||||
$change = ((string) $field['Type'] !== $column->Type) || ((string) $field['Null'] !== $column->Null)
|
||||
|| ((string) $field['Default'] !== $column->Default) || ((string) $field['Extra'] !== $column->Extra);
|
||||
|
||||
if ($change) {
|
||||
$alters[] = $this->getChangeColumnSql($table, $field);
|
||||
}
|
||||
|
||||
// Unset this field so that what we have left are fields that need to be removed.
|
||||
unset($oldFields[$fName]);
|
||||
} else {
|
||||
// The field is new.
|
||||
$alters[] = $this->getAddColumnSql($table, $field);
|
||||
}
|
||||
}
|
||||
|
||||
// Any columns left are orphans
|
||||
foreach ($oldFields as $name => $column) {
|
||||
// Delete the column.
|
||||
$alters[] = $this->getDropColumnSql($table, $name);
|
||||
}
|
||||
|
||||
// Get the lookups for the old and new keys.
|
||||
$oldLookup = $this->getKeyLookup($oldKeys);
|
||||
$newLookup = $this->getKeyLookup($newKeys);
|
||||
|
||||
// Loop through each key in the new structure.
|
||||
foreach ($newLookup as $name => $keys) {
|
||||
// Check if there are keys on this field in the existing table.
|
||||
if (isset($oldLookup[$name])) {
|
||||
$same = true;
|
||||
$newCount = \count($newLookup[$name]);
|
||||
$oldCount = \count($oldLookup[$name]);
|
||||
|
||||
// There is a key on this field in the old and new tables. Are they the same?
|
||||
if ($newCount === $oldCount) {
|
||||
// Need to loop through each key and do a fine grained check.
|
||||
for ($i = 0; $i < $newCount; $i++) {
|
||||
$same = (((string) $newLookup[$name][$i]['Non_unique'] === $oldLookup[$name][$i]->Non_unique)
|
||||
&& ((string) $newLookup[$name][$i]['Column_name'] === $oldLookup[$name][$i]->Column_name)
|
||||
&& ((string) $newLookup[$name][$i]['Seq_in_index'] === $oldLookup[$name][$i]->Seq_in_index)
|
||||
&& ((string) $newLookup[$name][$i]['Collation'] === $oldLookup[$name][$i]->Collation)
|
||||
&& ((string) $newLookup[$name][$i]['Sub_part'] === $oldLookup[$name][$i]->Sub_part)
|
||||
&& ((string) $newLookup[$name][$i]['Index_type'] === $oldLookup[$name][$i]->Index_type));
|
||||
|
||||
/*
|
||||
Debug.
|
||||
echo '<pre>';
|
||||
echo '<br>Non_unique: '.
|
||||
((string) $newLookup[$name][$i]['Non_unique'] == $oldLookup[$name][$i]->Non_unique ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Non_unique'].' vs '.$oldLookup[$name][$i]->Non_unique;
|
||||
echo '<br>Column_name: '.
|
||||
((string) $newLookup[$name][$i]['Column_name'] == $oldLookup[$name][$i]->Column_name ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Column_name'].' vs '.$oldLookup[$name][$i]->Column_name;
|
||||
echo '<br>Seq_in_index: '.
|
||||
((string) $newLookup[$name][$i]['Seq_in_index'] == $oldLookup[$name][$i]->Seq_in_index ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Seq_in_index'].' vs '.$oldLookup[$name][$i]->Seq_in_index;
|
||||
echo '<br>Collation: '.
|
||||
((string) $newLookup[$name][$i]['Collation'] == $oldLookup[$name][$i]->Collation ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Collation'].' vs '.$oldLookup[$name][$i]->Collation;
|
||||
echo '<br>Sub_part: '.
|
||||
((string) $newLookup[$name][$i]['Sub_part'] == $oldLookup[$name][$i]->Sub_part ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Sub_part'].' vs '.$oldLookup[$name][$i]->Sub_part;
|
||||
echo '<br>Index_type: '.
|
||||
((string) $newLookup[$name][$i]['Index_type'] == $oldLookup[$name][$i]->Index_type ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Index_type'].' vs '.$oldLookup[$name][$i]->Index_type;
|
||||
echo '<br>Same = '.($same ? 'true' : 'false');
|
||||
echo '</pre>';
|
||||
*/
|
||||
|
||||
if (!$same) {
|
||||
// Break out of the loop. No need to check further.
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Count is different, just drop and add.
|
||||
$same = false;
|
||||
}
|
||||
|
||||
if (!$same) {
|
||||
$alters[] = $this->getDropKeySql($table, $name);
|
||||
$alters[] = $this->getAddKeySql($table, $keys);
|
||||
}
|
||||
|
||||
// Unset this field so that what we have left are fields that need to be removed.
|
||||
unset($oldLookup[$name]);
|
||||
} else {
|
||||
// This is a new key.
|
||||
$alters[] = $this->getAddKeySql($table, $keys);
|
||||
}
|
||||
}
|
||||
|
||||
// Any keys left are orphans.
|
||||
foreach ($oldLookup as $name => $keys) {
|
||||
if (strtoupper($name) === 'PRIMARY') {
|
||||
$alters[] = $this->getDropPrimaryKeySql($table);
|
||||
} else {
|
||||
$alters[] = $this->getDropKeySql($table, $name);
|
||||
}
|
||||
}
|
||||
|
||||
return $alters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the syntax to alter a column.
|
||||
*
|
||||
* @param string $table The name of the database table to alter.
|
||||
* @param \SimpleXMLElement $field The XML definition for the field.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getChangeColumnSql($table, \SimpleXMLElement $field)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' CHANGE COLUMN ' . $this->db->quoteName((string) $field['Field']) . ' '
|
||||
. $this->getColumnSql($field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax for a single column that would be included in a table create or alter statement.
|
||||
*
|
||||
* @param \SimpleXMLElement $field The XML field definition.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getColumnSql(\SimpleXMLElement $field)
|
||||
{
|
||||
// Initialise variables.
|
||||
// TODO Incorporate into parent class and use $this.
|
||||
$blobs = ['text', 'smalltext', 'mediumtext', 'largetext'];
|
||||
|
||||
$fName = (string) $field['Field'];
|
||||
$fType = (string) $field['Type'];
|
||||
$fNull = (string) $field['Null'];
|
||||
$fDefault = isset($field['Default']) ? (string) $field['Default'] : null;
|
||||
$fExtra = (string) $field['Extra'];
|
||||
|
||||
$sql = $this->db->quoteName($fName) . ' ' . $fType;
|
||||
|
||||
if ($fNull === 'NO') {
|
||||
if ($fDefault === null || \in_array($fType, $blobs, true)) {
|
||||
$sql .= ' NOT NULL';
|
||||
} else {
|
||||
// TODO Don't quote numeric values.
|
||||
if (stristr($fDefault, 'CURRENT') !== false) {
|
||||
$sql .= ' NOT NULL DEFAULT CURRENT_TIMESTAMP()';
|
||||
} else {
|
||||
$sql .= ' NOT NULL DEFAULT ' . $this->db->quote($fDefault);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($fDefault === null) {
|
||||
$sql .= ' DEFAULT NULL';
|
||||
} else {
|
||||
// TODO Don't quote numeric values.
|
||||
$sql .= ' DEFAULT ' . $this->db->quote($fDefault);
|
||||
}
|
||||
}
|
||||
|
||||
if ($fExtra) {
|
||||
// MySql 8.0 introduces DEFAULT_GENERATED in the extra column and should be replaced with the default value
|
||||
if (stristr($fExtra, 'DEFAULT_GENERATED') !== false) {
|
||||
$sql .= ' ' . strtoupper(str_ireplace('DEFAULT_GENERATED', 'DEFAULT ' . $fDefault, $fExtra));
|
||||
} else {
|
||||
$sql .= ' ' . strtoupper($fExtra);
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param string $name The name of the key to drop.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getDropKeySql($table, $name)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP KEY ' . $this->db->quoteName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getDropPrimaryKeySql($table)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP PRIMARY KEY';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of keys for a table.
|
||||
*
|
||||
* @param array $keys An array of objects that comprise the keys for the table.
|
||||
*
|
||||
* @return array The lookup array. array({key name} => array(object, ...))
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getKeyLookup($keys)
|
||||
{
|
||||
// First pass, create a lookup of the keys.
|
||||
$lookup = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if ($key instanceof \SimpleXMLElement) {
|
||||
$kName = (string) $key['Key_name'];
|
||||
} else {
|
||||
$kName = $key->Key_name;
|
||||
}
|
||||
|
||||
if (empty($lookup[$kName])) {
|
||||
$lookup[$kName] = [];
|
||||
}
|
||||
|
||||
$lookup[$kName][] = $key;
|
||||
}
|
||||
|
||||
return $lookup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax for a key.
|
||||
*
|
||||
* @param array $columns An array of SimpleXMLElement objects comprising the key.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getKeySql($columns)
|
||||
{
|
||||
$kNonUnique = (string) $columns[0]['Non_unique'];
|
||||
$kName = (string) $columns[0]['Key_name'];
|
||||
$prefix = '';
|
||||
|
||||
if ($kName === 'PRIMARY') {
|
||||
$prefix = 'PRIMARY ';
|
||||
} elseif ($kNonUnique == 0) {
|
||||
$prefix = 'UNIQUE ';
|
||||
}
|
||||
|
||||
$kColumns = [];
|
||||
|
||||
foreach ($columns as $column) {
|
||||
$kLength = '';
|
||||
|
||||
if (!empty($column['Sub_part'])) {
|
||||
$kLength = '(' . $column['Sub_part'] . ')';
|
||||
}
|
||||
|
||||
$kColumns[] = $this->db->quoteName((string) $column['Column_name']) . $kLength;
|
||||
}
|
||||
|
||||
return $prefix . 'KEY ' . ($kName !== 'PRIMARY' ? $this->db->quoteName($kName) : '') . ' (' . implode(',', $kColumns) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add a table.
|
||||
*
|
||||
* @param \SimpleXMLElement $table The table information.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function xmlToCreate(\SimpleXMLElement $table)
|
||||
{
|
||||
$existingTables = $this->db->getTableList();
|
||||
$tableName = (string) $table['name'];
|
||||
|
||||
if (\in_array($tableName, $existingTables)) {
|
||||
throw new \RuntimeException('The table you are trying to create already exists');
|
||||
}
|
||||
|
||||
$createTableStatement = 'CREATE TABLE ' . $this->db->quoteName($tableName) . ' (';
|
||||
|
||||
foreach ($table->xpath('field') as $field) {
|
||||
$createTableStatement .= $this->getColumnSql($field) . ', ';
|
||||
}
|
||||
|
||||
$newLookup = $this->getKeyLookup($table->xpath('key'));
|
||||
|
||||
foreach ($newLookup as $key) {
|
||||
$createTableStatement .= $this->getKeySql($key) . ', ';
|
||||
}
|
||||
|
||||
$createTableStatement = rtrim($createTableStatement, ', ');
|
||||
|
||||
$createTableStatement .= ')';
|
||||
|
||||
return $createTableStatement;
|
||||
}
|
||||
}
|
||||
31
libraries/vendor/joomla/database/src/Mysql/MysqlQuery.php
vendored
Normal file
31
libraries/vendor/joomla/database/src/Mysql/MysqlQuery.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Mysql;
|
||||
|
||||
use Joomla\Database\Pdo\PdoQuery;
|
||||
use Joomla\Database\Query\MysqlQueryBuilder;
|
||||
|
||||
/**
|
||||
* MySQL Query Building Class.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class MysqlQuery extends PdoQuery
|
||||
{
|
||||
use MysqlQueryBuilder;
|
||||
|
||||
/**
|
||||
* The list of zero or null representation of a datetime.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $nullDatetimeList = ['0000-00-00 00:00:00', '1000-01-01 00:00:00'];
|
||||
}
|
||||
1085
libraries/vendor/joomla/database/src/Mysqli/MysqliDriver.php
vendored
Normal file
1085
libraries/vendor/joomla/database/src/Mysqli/MysqliDriver.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
116
libraries/vendor/joomla/database/src/Mysqli/MysqliExporter.php
vendored
Normal file
116
libraries/vendor/joomla/database/src/Mysqli/MysqliExporter.php
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Mysqli;
|
||||
|
||||
use Joomla\Database\DatabaseExporter;
|
||||
|
||||
/**
|
||||
* MySQLi Database Exporter.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class MysqliExporter extends DatabaseExporter
|
||||
{
|
||||
/**
|
||||
* Builds the XML data for the tables to export.
|
||||
*
|
||||
* @return string An XML string
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXml()
|
||||
{
|
||||
$buffer = [];
|
||||
|
||||
$buffer[] = '<?xml version="1.0"?>';
|
||||
$buffer[] = '<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
|
||||
$buffer[] = ' <database name="">';
|
||||
|
||||
if ($this->options->withStructure) {
|
||||
$buffer = array_merge($buffer, $this->buildXmlStructure());
|
||||
}
|
||||
|
||||
if ($this->options->withData) {
|
||||
$buffer = array_merge($buffer, $this->buildXmlData());
|
||||
}
|
||||
|
||||
$buffer[] = ' </database>';
|
||||
$buffer[] = '</mysqldump>';
|
||||
|
||||
return implode("\n", $buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XML structure to export.
|
||||
*
|
||||
* @return array An array of XML lines (strings).
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXmlStructure()
|
||||
{
|
||||
$buffer = [];
|
||||
|
||||
foreach ($this->from as $table) {
|
||||
// Replace the magic prefix if found.
|
||||
$table = $this->getGenericTableName($table);
|
||||
|
||||
// Get the details columns information.
|
||||
$fields = $this->db->getTableColumns($table, false);
|
||||
$keys = $this->db->getTableKeys($table);
|
||||
|
||||
$buffer[] = ' <table_structure name="' . $table . '">';
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$buffer[] = ' <field Field="' . $field->Field . '" Type="' . $field->Type . '" Null="' . $field->Null . '" Key="' .
|
||||
$field->Key . '"' . (isset($field->Default) ? ' Default="' . $field->Default . '"' : '') . ' Extra="' . $field->Extra . '"' .
|
||||
' />';
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$buffer[] = ' <key Table="' . $table . '" Non_unique="' . $key->Non_unique . '" Key_name="' . $key->Key_name . '"' .
|
||||
' Seq_in_index="' . $key->Seq_in_index . '" Column_name="' . $key->Column_name . '" Collation="' . $key->Collation . '"' .
|
||||
' Null="' . $key->Null . '" Index_type="' . $key->Index_type . '"' .
|
||||
' Sub_part="' . $key->Sub_part . '"' .
|
||||
' Comment="' . htmlspecialchars($key->Comment, \ENT_COMPAT, 'UTF-8') . '"' .
|
||||
' />';
|
||||
}
|
||||
|
||||
$buffer[] = ' </table_structure>';
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all data and options are in order prior to exporting.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
// Check if the db connector has been set.
|
||||
if (!($this->db instanceof MysqliDriver)) {
|
||||
throw new \RuntimeException('Database connection wrong type.');
|
||||
}
|
||||
|
||||
// Check if the tables have been specified.
|
||||
if (empty($this->from)) {
|
||||
throw new \RuntimeException('ERROR: No Tables Specified');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
395
libraries/vendor/joomla/database/src/Mysqli/MysqliImporter.php
vendored
Normal file
395
libraries/vendor/joomla/database/src/Mysqli/MysqliImporter.php
vendored
Normal file
@ -0,0 +1,395 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Mysqli;
|
||||
|
||||
use Joomla\Database\DatabaseImporter;
|
||||
|
||||
/**
|
||||
* MySQLi Database Importer.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class MysqliImporter extends DatabaseImporter
|
||||
{
|
||||
/**
|
||||
* Checks if all data and options are in order prior to exporting.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
// Check if the db connector has been set.
|
||||
if (!($this->db instanceof MysqliDriver)) {
|
||||
throw new \RuntimeException('Database connection wrong type.');
|
||||
}
|
||||
|
||||
// Check if the tables have been specified.
|
||||
if (empty($this->from)) {
|
||||
throw new \RuntimeException('ERROR: No Tables Specified');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add a table.
|
||||
*
|
||||
* @param \SimpleXMLElement $table The table information.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.4.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function xmlToCreate(\SimpleXMLElement $table)
|
||||
{
|
||||
$existingTables = $this->db->getTableList();
|
||||
$tableName = (string) $table['name'];
|
||||
|
||||
if (\in_array($tableName, $existingTables, true)) {
|
||||
throw new \RuntimeException('The table you are trying to create already exists');
|
||||
}
|
||||
|
||||
$createTableStatement = 'CREATE TABLE ' . $this->db->quoteName($tableName) . ' (';
|
||||
|
||||
foreach ($table->xpath('field') as $field) {
|
||||
$createTableStatement .= $this->getColumnSql($field) . ', ';
|
||||
}
|
||||
|
||||
$newLookup = $this->getKeyLookup($table->xpath('key'));
|
||||
|
||||
foreach ($newLookup as $key) {
|
||||
$createTableStatement .= $this->getKeySql($key) . ', ';
|
||||
}
|
||||
|
||||
$createTableStatement = rtrim($createTableStatement, ', ');
|
||||
|
||||
$createTableStatement .= ')';
|
||||
|
||||
return $createTableStatement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param array $keys An array of the fields pertaining to this key.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getAddKeySql($table, $keys)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' ADD ' . $this->getKeySql($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alters for table if there is a difference.
|
||||
*
|
||||
* @param \SimpleXMLElement $structure The XML structure of the table.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getAlterTableSql(\SimpleXMLElement $structure)
|
||||
{
|
||||
$table = $this->getRealTableName($structure['name']);
|
||||
$oldFields = $this->db->getTableColumns($table, false);
|
||||
$oldKeys = $this->db->getTableKeys($table);
|
||||
$alters = [];
|
||||
|
||||
// Get the fields and keys from the XML that we are aiming for.
|
||||
$newFields = $structure->xpath('field');
|
||||
$newKeys = $structure->xpath('key');
|
||||
|
||||
// Loop through each field in the new structure.
|
||||
foreach ($newFields as $field) {
|
||||
$fName = (string) $field['Field'];
|
||||
|
||||
if (isset($oldFields[$fName])) {
|
||||
// The field exists, check it's the same.
|
||||
$column = $oldFields[$fName];
|
||||
|
||||
// Test whether there is a change.
|
||||
$change = ((string) $field['Type'] !== $column->Type) || ((string) $field['Null'] !== $column->Null)
|
||||
|| ((string) $field['Default'] !== $column->Default) || ((string) $field['Extra'] !== $column->Extra);
|
||||
|
||||
if ($change) {
|
||||
$alters[] = $this->getChangeColumnSql($table, $field);
|
||||
}
|
||||
|
||||
// Unset this field so that what we have left are fields that need to be removed.
|
||||
unset($oldFields[$fName]);
|
||||
} else {
|
||||
// The field is new.
|
||||
$alters[] = $this->getAddColumnSql($table, $field);
|
||||
}
|
||||
}
|
||||
|
||||
// Any columns left are orphans
|
||||
foreach ($oldFields as $name => $column) {
|
||||
// Delete the column.
|
||||
$alters[] = $this->getDropColumnSql($table, $name);
|
||||
}
|
||||
|
||||
// Get the lookups for the old and new keys.
|
||||
$oldLookup = $this->getKeyLookup($oldKeys);
|
||||
$newLookup = $this->getKeyLookup($newKeys);
|
||||
|
||||
// Loop through each key in the new structure.
|
||||
foreach ($newLookup as $name => $keys) {
|
||||
// Check if there are keys on this field in the existing table.
|
||||
if (isset($oldLookup[$name])) {
|
||||
$same = true;
|
||||
$newCount = \count($newLookup[$name]);
|
||||
$oldCount = \count($oldLookup[$name]);
|
||||
|
||||
// There is a key on this field in the old and new tables. Are they the same?
|
||||
if ($newCount === $oldCount) {
|
||||
// Need to loop through each key and do a fine grained check.
|
||||
for ($i = 0; $i < $newCount; $i++) {
|
||||
$same = (((string) $newLookup[$name][$i]['Non_unique'] === $oldLookup[$name][$i]->Non_unique)
|
||||
&& ((string) $newLookup[$name][$i]['Column_name'] === $oldLookup[$name][$i]->Column_name)
|
||||
&& ((string) $newLookup[$name][$i]['Seq_in_index'] === $oldLookup[$name][$i]->Seq_in_index)
|
||||
&& ((string) $newLookup[$name][$i]['Collation'] === $oldLookup[$name][$i]->Collation)
|
||||
&& ((string) $newLookup[$name][$i]['Sub_part'] == $oldLookup[$name][$i]->Sub_part)
|
||||
&& ((string) $newLookup[$name][$i]['Index_type'] === $oldLookup[$name][$i]->Index_type));
|
||||
|
||||
/*
|
||||
Debug.
|
||||
echo '<pre>';
|
||||
echo '<br>Non_unique: '.
|
||||
((string) $newLookup[$name][$i]['Non_unique'] == $oldLookup[$name][$i]->Non_unique ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Non_unique'].' vs '.$oldLookup[$name][$i]->Non_unique;
|
||||
echo '<br>Column_name: '.
|
||||
((string) $newLookup[$name][$i]['Column_name'] == $oldLookup[$name][$i]->Column_name ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Column_name'].' vs '.$oldLookup[$name][$i]->Column_name;
|
||||
echo '<br>Seq_in_index: '.
|
||||
((string) $newLookup[$name][$i]['Seq_in_index'] == $oldLookup[$name][$i]->Seq_in_index ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Seq_in_index'].' vs '.$oldLookup[$name][$i]->Seq_in_index;
|
||||
echo '<br>Collation: '.
|
||||
((string) $newLookup[$name][$i]['Collation'] == $oldLookup[$name][$i]->Collation ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Collation'].' vs '.$oldLookup[$name][$i]->Collation;
|
||||
echo '<br>Sub_part: '.
|
||||
((string) $newLookup[$name][$i]['Sub_part'] == $oldLookup[$name][$i]->Sub_part ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Sub_part'].' vs '.$oldLookup[$name][$i]->Sub_part;
|
||||
echo '<br>Index_type: '.
|
||||
((string) $newLookup[$name][$i]['Index_type'] == $oldLookup[$name][$i]->Index_type ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Index_type'].' vs '.$oldLookup[$name][$i]->Index_type;
|
||||
echo '<br>Same = '.($same ? 'true' : 'false');
|
||||
echo '</pre>';
|
||||
*/
|
||||
|
||||
if (!$same) {
|
||||
// Break out of the loop. No need to check further.
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Count is different, just drop and add.
|
||||
$same = false;
|
||||
}
|
||||
|
||||
if (!$same) {
|
||||
$alters[] = $this->getDropKeySql($table, $name);
|
||||
$alters[] = $this->getAddKeySql($table, $keys);
|
||||
}
|
||||
|
||||
// Unset this field so that what we have left are fields that need to be removed.
|
||||
unset($oldLookup[$name]);
|
||||
} else {
|
||||
// This is a new key.
|
||||
$alters[] = $this->getAddKeySql($table, $keys);
|
||||
}
|
||||
}
|
||||
|
||||
// Any keys left are orphans.
|
||||
foreach ($oldLookup as $name => $keys) {
|
||||
if (strtoupper($name) === 'PRIMARY') {
|
||||
$alters[] = $this->getDropPrimaryKeySql($table);
|
||||
} else {
|
||||
$alters[] = $this->getDropKeySql($table, $name);
|
||||
}
|
||||
}
|
||||
|
||||
return $alters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the syntax to alter a column.
|
||||
*
|
||||
* @param string $table The name of the database table to alter.
|
||||
* @param \SimpleXMLElement $field The XML definition for the field.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getChangeColumnSql($table, \SimpleXMLElement $field)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' CHANGE COLUMN ' . $this->db->quoteName((string) $field['Field']) . ' '
|
||||
. $this->getColumnSql($field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax for a single column that would be included in a table create or alter statement.
|
||||
*
|
||||
* @param \SimpleXMLElement $field The XML field definition.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getColumnSql(\SimpleXMLElement $field)
|
||||
{
|
||||
// TODO Incorporate into parent class and use $this.
|
||||
$blobs = ['text', 'smalltext', 'mediumtext', 'largetext'];
|
||||
|
||||
$fName = (string) $field['Field'];
|
||||
$fType = (string) $field['Type'];
|
||||
$fNull = (string) $field['Null'];
|
||||
$fDefault = isset($field['Default']) ? (string) $field['Default'] : null;
|
||||
$fExtra = (string) $field['Extra'];
|
||||
|
||||
$sql = $this->db->quoteName($fName) . ' ' . $fType;
|
||||
|
||||
if ($fNull === 'NO') {
|
||||
if ($fDefault === null || \in_array($fType, $blobs, true)) {
|
||||
$sql .= ' NOT NULL';
|
||||
} else {
|
||||
// TODO Don't quote numeric values.
|
||||
if (stristr($fDefault, 'CURRENT') !== false) {
|
||||
$sql .= ' NOT NULL DEFAULT CURRENT_TIMESTAMP()';
|
||||
} else {
|
||||
$sql .= ' NOT NULL DEFAULT ' . $this->db->quote($fDefault);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($fDefault === null) {
|
||||
$sql .= ' DEFAULT NULL';
|
||||
} else {
|
||||
// TODO Don't quote numeric values.
|
||||
$sql .= ' DEFAULT ' . $this->db->quote($fDefault);
|
||||
}
|
||||
}
|
||||
|
||||
if ($fExtra) {
|
||||
// MySql 8.0 introduces DEFAULT_GENERATED in the extra column and should be replaced with the default value
|
||||
if (stristr($fExtra, 'DEFAULT_GENERATED') !== false) {
|
||||
$sql .= ' ' . strtoupper(str_ireplace('DEFAULT_GENERATED', 'DEFAULT ' . $fDefault, $fExtra));
|
||||
} else {
|
||||
$sql .= ' ' . strtoupper($fExtra);
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param string $name The name of the key to drop.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getDropKeySql($table, $name)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP KEY ' . $this->db->quoteName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getDropPrimaryKeySql($table)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP PRIMARY KEY';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of keys for a table.
|
||||
*
|
||||
* @param array $keys An array of objects that comprise the keys for the table.
|
||||
*
|
||||
* @return array The lookup array. array({key name} => array(object, ...))
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getKeyLookup($keys)
|
||||
{
|
||||
// First pass, create a lookup of the keys.
|
||||
$lookup = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if ($key instanceof \SimpleXMLElement) {
|
||||
$kName = (string) $key['Key_name'];
|
||||
} else {
|
||||
$kName = $key->Key_name;
|
||||
}
|
||||
|
||||
if (empty($lookup[$kName])) {
|
||||
$lookup[$kName] = [];
|
||||
}
|
||||
|
||||
$lookup[$kName][] = $key;
|
||||
}
|
||||
|
||||
return $lookup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax for a key.
|
||||
*
|
||||
* @param array $columns An array of SimpleXMLElement objects comprising the key.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getKeySql($columns)
|
||||
{
|
||||
$kNonUnique = (string) $columns[0]['Non_unique'];
|
||||
$kName = (string) $columns[0]['Key_name'];
|
||||
$prefix = '';
|
||||
|
||||
if ($kName === 'PRIMARY') {
|
||||
$prefix = 'PRIMARY ';
|
||||
} elseif ($kNonUnique == 0) {
|
||||
$prefix = 'UNIQUE ';
|
||||
}
|
||||
|
||||
$kColumns = [];
|
||||
|
||||
foreach ($columns as $column) {
|
||||
$kLength = '';
|
||||
|
||||
if (!empty($column['Sub_part'])) {
|
||||
$kLength = '(' . $column['Sub_part'] . ')';
|
||||
}
|
||||
|
||||
$kColumns[] = $this->db->quoteName((string) $column['Column_name']) . $kLength;
|
||||
}
|
||||
|
||||
return $prefix . 'KEY ' . ($kName !== 'PRIMARY' ? $this->db->quoteName($kName) : '') . ' (' . implode(',', $kColumns) . ')';
|
||||
}
|
||||
}
|
||||
31
libraries/vendor/joomla/database/src/Mysqli/MysqliQuery.php
vendored
Normal file
31
libraries/vendor/joomla/database/src/Mysqli/MysqliQuery.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Mysqli;
|
||||
|
||||
use Joomla\Database\DatabaseQuery;
|
||||
use Joomla\Database\Query\MysqlQueryBuilder;
|
||||
|
||||
/**
|
||||
* MySQLi Query Building Class.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class MysqliQuery extends DatabaseQuery
|
||||
{
|
||||
use MysqlQueryBuilder;
|
||||
|
||||
/**
|
||||
* The list of zero or null representation of a datetime.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $nullDatetimeList = ['0000-00-00 00:00:00', '1000-01-01 00:00:00'];
|
||||
}
|
||||
580
libraries/vendor/joomla/database/src/Mysqli/MysqliStatement.php
vendored
Normal file
580
libraries/vendor/joomla/database/src/Mysqli/MysqliStatement.php
vendored
Normal file
@ -0,0 +1,580 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Mysqli;
|
||||
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use Joomla\Database\Exception\PrepareStatementFailureException;
|
||||
use Joomla\Database\FetchMode;
|
||||
use Joomla\Database\FetchOrientation;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Database\StatementInterface;
|
||||
|
||||
/**
|
||||
* MySQLi Database Statement.
|
||||
*
|
||||
* This class is modeled on \Doctrine\DBAL\Driver\Mysqli\MysqliStatement
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class MysqliStatement implements StatementInterface
|
||||
{
|
||||
/**
|
||||
* Values which have been bound to the statement.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $bindedValues;
|
||||
|
||||
/**
|
||||
* Mapping between named parameters and position in query.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $parameterKeyMapping;
|
||||
|
||||
/**
|
||||
* Mapping array for parameter types.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $parameterTypeMapping = [
|
||||
ParameterType::BOOLEAN => 'i',
|
||||
ParameterType::INTEGER => 'i',
|
||||
ParameterType::LARGE_OBJECT => 's',
|
||||
ParameterType::NULL => 's',
|
||||
ParameterType::STRING => 's',
|
||||
];
|
||||
|
||||
/**
|
||||
* Column names from the executed statement.
|
||||
*
|
||||
* @var array|boolean|null
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $columnNames;
|
||||
|
||||
/**
|
||||
* The database connection resource.
|
||||
*
|
||||
* @var \mysqli
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The default fetch mode for the statement.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $defaultFetchStyle = FetchMode::MIXED;
|
||||
|
||||
/**
|
||||
* The query string being prepared.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* Internal tracking flag to set whether there is a result set available for processing
|
||||
*
|
||||
* @var boolean
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $result = false;
|
||||
|
||||
/**
|
||||
* Values which have been bound to the rows of each result set.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $rowBindedValues;
|
||||
|
||||
/**
|
||||
* The prepared statement.
|
||||
*
|
||||
* @var \mysqli_stmt
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $statement;
|
||||
|
||||
/**
|
||||
* Bound parameter types.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $typesKeyMapping;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \mysqli $connection The database connection resource
|
||||
* @param string $query The query this statement will process
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws PrepareStatementFailureException
|
||||
*/
|
||||
public function __construct(\mysqli $connection, string $query)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->query = $query;
|
||||
|
||||
$query = $this->prepareParameterKeyMapping($query);
|
||||
|
||||
$this->statement = $connection->prepare($query);
|
||||
|
||||
if (!$this->statement) {
|
||||
throw new PrepareStatementFailureException($this->connection->error, $this->connection->errno);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace named parameters with numbered parameters
|
||||
*
|
||||
* @param string $sql The SQL statement to prepare.
|
||||
*
|
||||
* @return string The processed SQL statement.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function prepareParameterKeyMapping($sql)
|
||||
{
|
||||
$escaped = false;
|
||||
$startPos = 0;
|
||||
$quoteChar = '';
|
||||
$literal = '';
|
||||
$mapping = [];
|
||||
$replace = [];
|
||||
$matches = [];
|
||||
$pattern = '/([:][a-zA-Z0-9_]+)/';
|
||||
|
||||
if (!preg_match($pattern, $sql, $matches)) {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
$sql = trim($sql);
|
||||
$n = \strlen($sql);
|
||||
|
||||
while ($startPos < $n) {
|
||||
if (!preg_match($pattern, $sql, $matches, 0, $startPos)) {
|
||||
break;
|
||||
}
|
||||
|
||||
$j = strpos($sql, "'", $startPos);
|
||||
$k = strpos($sql, '"', $startPos);
|
||||
|
||||
if (($k !== false) && (($k < $j) || ($j === false))) {
|
||||
$quoteChar = '"';
|
||||
$j = $k;
|
||||
} else {
|
||||
$quoteChar = "'";
|
||||
}
|
||||
|
||||
if ($j === false) {
|
||||
$j = $n;
|
||||
}
|
||||
|
||||
// Search for named prepared parameters and replace it with ? and save its position
|
||||
$substring = substr($sql, $startPos, $j - $startPos);
|
||||
|
||||
if (preg_match_all($pattern, $substring, $matches, PREG_PATTERN_ORDER + PREG_OFFSET_CAPTURE)) {
|
||||
foreach ($matches[0] as $i => $match) {
|
||||
if ($i === 0) {
|
||||
$literal .= substr($substring, 0, $match[1]);
|
||||
}
|
||||
|
||||
$mapping[$match[0]] = \count($mapping);
|
||||
$endOfPlaceholder = $match[1] + strlen($match[0]);
|
||||
$beginOfNextPlaceholder = $matches[0][$i + 1][1] ?? strlen($substring);
|
||||
$beginOfNextPlaceholder -= $endOfPlaceholder;
|
||||
$literal .= '?' . substr($substring, $endOfPlaceholder, $beginOfNextPlaceholder);
|
||||
}
|
||||
} else {
|
||||
$literal .= $substring;
|
||||
}
|
||||
|
||||
$startPos = $j;
|
||||
$j++;
|
||||
|
||||
if ($j >= $n) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Quote comes first, find end of quote
|
||||
while (true) {
|
||||
$k = strpos($sql, $quoteChar, $j);
|
||||
$escaped = false;
|
||||
|
||||
if ($k === false) {
|
||||
break;
|
||||
}
|
||||
|
||||
$l = $k - 1;
|
||||
|
||||
while ($l >= 0 && $sql[$l] === '\\') {
|
||||
$l--;
|
||||
$escaped = !$escaped;
|
||||
}
|
||||
|
||||
if ($escaped) {
|
||||
$j = $k + 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($k === false) {
|
||||
// Error in the query - no end quote; ignore it
|
||||
break;
|
||||
}
|
||||
|
||||
$literal .= substr($sql, $startPos, $k - $startPos + 1);
|
||||
$startPos = $k + 1;
|
||||
}
|
||||
|
||||
if ($startPos < $n) {
|
||||
$literal .= substr($sql, $startPos, $n - $startPos);
|
||||
}
|
||||
|
||||
$this->parameterKeyMapping = $mapping;
|
||||
|
||||
return $literal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a parameter to the specified variable name.
|
||||
*
|
||||
* @param string|integer $parameter Parameter identifier. For a prepared statement using named placeholders, this will be a parameter
|
||||
* name of the form `:name`. For a prepared statement using question mark placeholders, this will be
|
||||
* the 1-indexed position of the parameter.
|
||||
* @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter.
|
||||
* @param integer $dataType Constant corresponding to a SQL datatype, this should be the processed type from the QueryInterface.
|
||||
* @param integer $length The length of the variable. Usually required for OUTPUT parameters.
|
||||
* @param array $driverOptions Optional driver options to be used.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function bindParam($parameter, &$variable, string $dataType = ParameterType::STRING, ?int $length = null, ?array $driverOptions = null)
|
||||
{
|
||||
$this->bindedValues[$parameter] =& $variable;
|
||||
|
||||
// Validate parameter type
|
||||
if (!isset($this->parameterTypeMapping[$dataType])) {
|
||||
throw new \InvalidArgumentException(sprintf('Unsupported parameter type `%s`', $dataType));
|
||||
}
|
||||
|
||||
$this->typesKeyMapping[$parameter] = $this->parameterTypeMapping[$dataType];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a array of values to bound parameters.
|
||||
*
|
||||
* @param array $values The values to bind to the statement
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private function bindValues(array $values)
|
||||
{
|
||||
$params = [];
|
||||
$types = str_repeat('s', \count($values));
|
||||
|
||||
if (!empty($this->parameterKeyMapping)) {
|
||||
foreach ($values as $key => &$value) {
|
||||
$params[$this->parameterKeyMapping[$key]] =& $value;
|
||||
}
|
||||
|
||||
ksort($params);
|
||||
} else {
|
||||
foreach ($values as $key => &$value) {
|
||||
$params[] =& $value;
|
||||
}
|
||||
}
|
||||
|
||||
array_unshift($params, $types);
|
||||
|
||||
return \call_user_func_array([$this->statement, 'bind_param'], $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the cursor, enabling the statement to be executed again.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function closeCursor(): void
|
||||
{
|
||||
$this->statement->free_result();
|
||||
$this->result = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the SQLSTATE associated with the last operation on the statement handle.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function errorCode()
|
||||
{
|
||||
return $this->statement->errno;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches extended error information associated with the last operation on the statement handle.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function errorInfo()
|
||||
{
|
||||
return $this->statement->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a prepared statement
|
||||
*
|
||||
* @param array|null $parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function execute(?array $parameters = null)
|
||||
{
|
||||
if ($this->bindedValues !== null) {
|
||||
$params = [];
|
||||
$types = [];
|
||||
|
||||
if (!empty($this->parameterKeyMapping)) {
|
||||
foreach ($this->bindedValues as $key => &$value) {
|
||||
$params[$this->parameterKeyMapping[$key]] =& $value;
|
||||
$types[$this->parameterKeyMapping[$key]] = $this->typesKeyMapping[$key];
|
||||
}
|
||||
} else {
|
||||
foreach ($this->bindedValues as $key => &$value) {
|
||||
$params[] =& $value;
|
||||
$types[$key] = $this->typesKeyMapping[$key];
|
||||
}
|
||||
}
|
||||
|
||||
ksort($params);
|
||||
ksort($types);
|
||||
|
||||
array_unshift($params, implode('', $types));
|
||||
|
||||
if (!\call_user_func_array([$this->statement, 'bind_param'], $params)) {
|
||||
throw new PrepareStatementFailureException($this->statement->error, $this->statement->errno);
|
||||
}
|
||||
} elseif ($parameters !== null) {
|
||||
if (!$this->bindValues($parameters)) {
|
||||
throw new PrepareStatementFailureException($this->statement->error, $this->statement->errno);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (!$this->statement->execute()) {
|
||||
throw new ExecutionFailureException($this->query, $this->statement->error, $this->statement->errno);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
throw new ExecutionFailureException($this->query, $e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
if ($this->columnNames === null) {
|
||||
$meta = $this->statement->result_metadata();
|
||||
|
||||
if ($meta !== false) {
|
||||
$columnNames = [];
|
||||
|
||||
foreach ($meta->fetch_fields() as $col) {
|
||||
$columnNames[] = $col->name;
|
||||
}
|
||||
|
||||
$meta->free();
|
||||
|
||||
$this->columnNames = $columnNames;
|
||||
} else {
|
||||
$this->columnNames = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->columnNames !== false) {
|
||||
$this->statement->store_result();
|
||||
|
||||
$this->rowBindedValues = array_fill(0, \count($this->columnNames), null);
|
||||
$refs = [];
|
||||
|
||||
foreach ($this->rowBindedValues as $key => &$value) {
|
||||
$refs[$key] =& $value;
|
||||
}
|
||||
|
||||
if (!\call_user_func_array([$this->statement, 'bind_result'], $refs)) {
|
||||
throw new \RuntimeException($this->statement->error, $this->statement->errno);
|
||||
}
|
||||
}
|
||||
|
||||
$this->result = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the next row from a result set
|
||||
*
|
||||
* @param integer|null $fetchStyle Controls how the next row will be returned to the caller. This value must be one of the
|
||||
* FetchMode constants, defaulting to value of FetchMode::MIXED.
|
||||
* @param integer $cursorOrientation For a StatementInterface object representing a scrollable cursor, this value determines which row
|
||||
* will be returned to the caller. This value must be one of the FetchOrientation constants,
|
||||
* defaulting to FetchOrientation::NEXT.
|
||||
* @param integer $cursorOffset For a StatementInterface object representing a scrollable cursor for which the cursorOrientation
|
||||
* parameter is set to FetchOrientation::ABS, this value specifies the absolute number of the row in
|
||||
* the result set that shall be fetched. For a StatementInterface object representing a scrollable
|
||||
* cursor for which the cursorOrientation parameter is set to FetchOrientation::REL, this value
|
||||
* specifies the row to fetch relative to the cursor position before `fetch()` was called.
|
||||
*
|
||||
* @return mixed The return value of this function on success depends on the fetch type. In all cases, boolean false is returned on failure.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function fetch(?int $fetchStyle = null, int $cursorOrientation = FetchOrientation::NEXT, int $cursorOffset = 0)
|
||||
{
|
||||
if (!$this->result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$fetchStyle = $fetchStyle ?: $this->defaultFetchStyle;
|
||||
|
||||
if ($fetchStyle === FetchMode::COLUMN) {
|
||||
return $this->fetchColumn();
|
||||
}
|
||||
|
||||
$values = $this->fetchData();
|
||||
|
||||
if ($values === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($values === false) {
|
||||
throw new \RuntimeException($this->statement->error, $this->statement->errno);
|
||||
}
|
||||
|
||||
switch ($fetchStyle) {
|
||||
case FetchMode::NUMERIC:
|
||||
return $values;
|
||||
|
||||
case FetchMode::ASSOCIATIVE:
|
||||
return array_combine($this->columnNames, $values);
|
||||
|
||||
case FetchMode::MIXED:
|
||||
$ret = array_combine($this->columnNames, $values);
|
||||
$ret += $values;
|
||||
|
||||
return $ret;
|
||||
|
||||
case FetchMode::STANDARD_OBJECT:
|
||||
return (object) array_combine($this->columnNames, $values);
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unknown fetch type '{$fetchStyle}'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single column from the next row of a result set
|
||||
*
|
||||
* @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row.
|
||||
* If no value is supplied, the first column is retrieved.
|
||||
*
|
||||
* @return mixed Returns a single column from the next row of a result set or boolean false if there are no more rows.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function fetchColumn($columnIndex = 0)
|
||||
{
|
||||
$row = $this->fetch(FetchMode::NUMERIC);
|
||||
|
||||
if ($row === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $row[$columnIndex] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the data from the statement.
|
||||
*
|
||||
* @return array|boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private function fetchData()
|
||||
{
|
||||
$return = $this->statement->fetch();
|
||||
|
||||
if ($return === true) {
|
||||
$values = [];
|
||||
|
||||
foreach ($this->rowBindedValues as $v) {
|
||||
$values[] = $v;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of rows affected by the last SQL statement.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function rowCount(): int
|
||||
{
|
||||
if ($this->columnNames === false) {
|
||||
return $this->statement->affected_rows;
|
||||
}
|
||||
|
||||
return $this->statement->num_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fetch mode to use while iterating this statement.
|
||||
*
|
||||
* @param integer $fetchMode The fetch mode, must be one of the FetchMode constants.
|
||||
* @param mixed ...$args Optional mode-specific arguments.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function setFetchMode(int $fetchMode, ...$args): void
|
||||
{
|
||||
$this->defaultFetchStyle = $fetchMode;
|
||||
}
|
||||
}
|
||||
67
libraries/vendor/joomla/database/src/ParameterType.php
vendored
Normal file
67
libraries/vendor/joomla/database/src/ParameterType.php
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Class defining the parameter types for prepared statements
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
final class ParameterType
|
||||
{
|
||||
/**
|
||||
* Defines a boolean parameter
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const BOOLEAN = 'boolean';
|
||||
|
||||
/**
|
||||
* Defines an integer parameter
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const INTEGER = 'int';
|
||||
|
||||
/**
|
||||
* Defines a large object parameter
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const LARGE_OBJECT = 'lob';
|
||||
|
||||
/**
|
||||
* Defines a null parameter
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const NULL = 'null';
|
||||
|
||||
/**
|
||||
* Defines a string parameter
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public const STRING = 'string';
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation of this class
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
748
libraries/vendor/joomla/database/src/Pdo/PdoDriver.php
vendored
Normal file
748
libraries/vendor/joomla/database/src/Pdo/PdoDriver.php
vendored
Normal file
@ -0,0 +1,748 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Pdo;
|
||||
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\DatabaseEvents;
|
||||
use Joomla\Database\Event\ConnectionEvent;
|
||||
use Joomla\Database\Exception\ConnectionFailureException;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use Joomla\Database\Exception\PrepareStatementFailureException;
|
||||
use Joomla\Database\Exception\UnsupportedAdapterException;
|
||||
use Joomla\Database\StatementInterface;
|
||||
|
||||
/**
|
||||
* Joomla Framework PDO Database Driver Class
|
||||
*
|
||||
* @link https://www.php.net/pdo
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract class PdoDriver extends DatabaseDriver
|
||||
{
|
||||
/**
|
||||
* The database connection resource.
|
||||
*
|
||||
* @var \PDO
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The name of the database driver.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public $name = 'pdo';
|
||||
|
||||
/**
|
||||
* The character(s) used to quote SQL statement names such as table names or field names, etc.
|
||||
*
|
||||
* If a single character string the same character is used for both sides of the quoted name, else the first character will be used for the
|
||||
* opening quote and the second for the closing quote.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $nameQuote = "'";
|
||||
|
||||
/**
|
||||
* The null or zero representation of a timestamp for the database driver.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $nullDate = '0000-00-00 00:00:00';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $options List of options used to configure the connection
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __construct(array $options)
|
||||
{
|
||||
// Get some basic values from the options.
|
||||
$options['driver'] = $options['driver'] ?? 'odbc';
|
||||
$options['dsn'] = $options['dsn'] ?? '';
|
||||
$options['host'] = $options['host'] ?? 'localhost';
|
||||
$options['database'] = $options['database'] ?? '';
|
||||
$options['user'] = $options['user'] ?? '';
|
||||
$options['port'] = isset($options['port']) ? (int) $options['port'] : null;
|
||||
$options['password'] = $options['password'] ?? '';
|
||||
$options['driverOptions'] = $options['driverOptions'] ?? [];
|
||||
$options['ssl'] = isset($options['ssl']) ? $options['ssl'] : [];
|
||||
$options['socket'] = \strpos($options['host'], 'unix:') !== false ? \str_replace('unix:', '', $options['host']) : null;
|
||||
|
||||
if ($options['ssl'] !== []) {
|
||||
$options['ssl']['enable'] = isset($options['ssl']['enable']) ? $options['ssl']['enable'] : false;
|
||||
$options['ssl']['cipher'] = isset($options['ssl']['cipher']) ? $options['ssl']['cipher'] : null;
|
||||
$options['ssl']['ca'] = isset($options['ssl']['ca']) ? $options['ssl']['ca'] : null;
|
||||
$options['ssl']['capath'] = isset($options['ssl']['capath']) ? $options['ssl']['capath'] : null;
|
||||
$options['ssl']['key'] = isset($options['ssl']['key']) ? $options['ssl']['key'] : null;
|
||||
$options['ssl']['cert'] = isset($options['ssl']['cert']) ? $options['ssl']['cert'] : null;
|
||||
$options['ssl']['verify_server_cert'] = isset($options['ssl']['verify_server_cert']) ? $options['ssl']['verify_server_cert'] : null;
|
||||
}
|
||||
|
||||
// Finalize initialisation
|
||||
parent::__construct($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the database if needed.
|
||||
*
|
||||
* @return void Returns void if the database connected successfully.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
if ($this->connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the PDO extension for PHP is installed and enabled.
|
||||
if (!static::isSupported()) {
|
||||
throw new UnsupportedAdapterException('PDO Extension is not available.', 1);
|
||||
}
|
||||
|
||||
// Find the correct PDO DSN Format to use:
|
||||
switch ($this->options['driver']) {
|
||||
case 'cubrid':
|
||||
$this->options['port'] = $this->options['port'] ?? 33000;
|
||||
|
||||
$format = 'cubrid:host=#HOST#;port=#PORT#;dbname=#DBNAME#';
|
||||
|
||||
$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
|
||||
$with = [$this->options['host'], $this->options['port'], $this->options['database']];
|
||||
|
||||
break;
|
||||
|
||||
case 'dblib':
|
||||
$this->options['port'] = $this->options['port'] ?? 1433;
|
||||
|
||||
$format = 'dblib:host=#HOST#;port=#PORT#;dbname=#DBNAME#';
|
||||
|
||||
$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
|
||||
$with = [$this->options['host'], $this->options['port'], $this->options['database']];
|
||||
|
||||
break;
|
||||
|
||||
case 'firebird':
|
||||
$this->options['port'] = $this->options['port'] ?? 3050;
|
||||
|
||||
$format = 'firebird:dbname=#DBNAME#';
|
||||
|
||||
$replace = ['#DBNAME#'];
|
||||
$with = [$this->options['database']];
|
||||
|
||||
break;
|
||||
|
||||
case 'ibm':
|
||||
$this->options['port'] = $this->options['port'] ?? 56789;
|
||||
|
||||
if (!empty($this->options['dsn'])) {
|
||||
$format = 'ibm:DSN=#DSN#';
|
||||
|
||||
$replace = ['#DSN#'];
|
||||
$with = [$this->options['dsn']];
|
||||
} else {
|
||||
$format = 'ibm:hostname=#HOST#;port=#PORT#;database=#DBNAME#';
|
||||
|
||||
$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
|
||||
$with = [$this->options['host'], $this->options['port'], $this->options['database']];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'informix':
|
||||
$this->options['port'] = $this->options['port'] ?? 1526;
|
||||
$this->options['protocol'] = $this->options['protocol'] ?? 'onsoctcp';
|
||||
|
||||
if (!empty($this->options['dsn'])) {
|
||||
$format = 'informix:DSN=#DSN#';
|
||||
|
||||
$replace = ['#DSN#'];
|
||||
$with = [$this->options['dsn']];
|
||||
} else {
|
||||
$format = 'informix:host=#HOST#;service=#PORT#;database=#DBNAME#;server=#SERVER#;protocol=#PROTOCOL#';
|
||||
|
||||
$replace = ['#HOST#', '#PORT#', '#DBNAME#', '#SERVER#', '#PROTOCOL#'];
|
||||
$with = [
|
||||
$this->options['host'],
|
||||
$this->options['port'],
|
||||
$this->options['database'],
|
||||
$this->options['server'],
|
||||
$this->options['protocol'],
|
||||
];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'mssql':
|
||||
$this->options['port'] = $this->options['port'] ?? 1433;
|
||||
|
||||
$format = 'mssql:host=#HOST#;port=#PORT#;dbname=#DBNAME#';
|
||||
|
||||
$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
|
||||
$with = [$this->options['host'], $this->options['port'], $this->options['database']];
|
||||
|
||||
break;
|
||||
|
||||
case 'mysql':
|
||||
$this->options['port'] = $this->options['port'] ?? 3306;
|
||||
|
||||
if ($this->options['socket'] !== null) {
|
||||
$format = 'mysql:unix_socket=#SOCKET#;dbname=#DBNAME#;charset=#CHARSET#';
|
||||
} else {
|
||||
$format = 'mysql:host=#HOST#;port=#PORT#;dbname=#DBNAME#;charset=#CHARSET#';
|
||||
}
|
||||
|
||||
$replace = ['#HOST#', '#PORT#', '#SOCKET#', '#DBNAME#', '#CHARSET#'];
|
||||
$with = [
|
||||
$this->options['host'],
|
||||
$this->options['port'],
|
||||
$this->options['socket'],
|
||||
$this->options['database'],
|
||||
$this->options['charset'],
|
||||
];
|
||||
|
||||
break;
|
||||
|
||||
case 'oci':
|
||||
$this->options['port'] = $this->options['port'] ?? 1521;
|
||||
$this->options['charset'] = $this->options['charset'] ?? 'AL32UTF8';
|
||||
|
||||
if (!empty($this->options['dsn'])) {
|
||||
$format = 'oci:dbname=#DSN#';
|
||||
|
||||
$replace = ['#DSN#'];
|
||||
$with = [$this->options['dsn']];
|
||||
} else {
|
||||
$format = 'oci:dbname=//#HOST#:#PORT#/#DBNAME#';
|
||||
|
||||
$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
|
||||
$with = [$this->options['host'], $this->options['port'], $this->options['database']];
|
||||
}
|
||||
|
||||
$format .= ';charset=' . $this->options['charset'];
|
||||
|
||||
break;
|
||||
|
||||
case 'odbc':
|
||||
$format = 'odbc:DSN=#DSN#;UID:#USER#;PWD=#PASSWORD#';
|
||||
|
||||
$replace = ['#DSN#', '#USER#', '#PASSWORD#'];
|
||||
$with = [$this->options['dsn'], $this->options['user'], $this->options['password']];
|
||||
|
||||
break;
|
||||
|
||||
case 'pgsql':
|
||||
$this->options['port'] = $this->options['port'] ?? 5432;
|
||||
|
||||
if ($this->options['socket'] !== null) {
|
||||
$format = 'pgsql:host=#SOCKET#;dbname=#DBNAME#';
|
||||
} else {
|
||||
$format = 'pgsql:host=#HOST#;port=#PORT#;dbname=#DBNAME#';
|
||||
}
|
||||
|
||||
$replace = ['#HOST#', '#PORT#', '#SOCKET#', '#DBNAME#'];
|
||||
$with = [$this->options['host'], $this->options['port'], $this->options['socket'], $this->options['database']];
|
||||
|
||||
// For data in transit TLS encryption.
|
||||
if ($this->options['ssl'] !== [] && $this->options['ssl']['enable'] === true) {
|
||||
if (isset($this->options['ssl']['verify_server_cert']) && $this->options['ssl']['verify_server_cert'] === true) {
|
||||
$format .= ';sslmode=verify-full';
|
||||
} else {
|
||||
$format .= ';sslmode=require';
|
||||
}
|
||||
|
||||
$sslKeysMapping = [
|
||||
'cipher' => null,
|
||||
'ca' => 'sslrootcert',
|
||||
'capath' => null,
|
||||
'key' => 'sslkey',
|
||||
'cert' => 'sslcert',
|
||||
];
|
||||
|
||||
// If customised, add cipher suite, ca file path, ca path, private key file path and certificate file path to PDO driver options.
|
||||
foreach ($sslKeysMapping as $key => $value) {
|
||||
if ($value !== null && $this->options['ssl'][$key] !== null) {
|
||||
$format .= ';' . $value . '=' . $this->options['ssl'][$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'sqlite':
|
||||
if (isset($this->options['version']) && $this->options['version'] == 2) {
|
||||
$format = 'sqlite2:#DBNAME#';
|
||||
} else {
|
||||
$format = 'sqlite:#DBNAME#';
|
||||
}
|
||||
|
||||
$replace = ['#DBNAME#'];
|
||||
$with = [$this->options['database']];
|
||||
|
||||
break;
|
||||
|
||||
case 'sybase':
|
||||
$this->options['port'] = $this->options['port'] ?? 1433;
|
||||
|
||||
$format = 'mssql:host=#HOST#;port=#PORT#;dbname=#DBNAME#';
|
||||
|
||||
$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
|
||||
$with = [$this->options['host'], $this->options['port'], $this->options['database']];
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new UnsupportedAdapterException('The ' . $this->options['driver'] . ' driver is not supported.');
|
||||
}
|
||||
|
||||
// Create the connection string:
|
||||
$connectionString = str_replace($replace, $with, $format);
|
||||
|
||||
try {
|
||||
$this->connection = new \PDO(
|
||||
$connectionString,
|
||||
$this->options['user'],
|
||||
$this->options['password'],
|
||||
$this->options['driverOptions']
|
||||
);
|
||||
} catch (\PDOException $e) {
|
||||
throw new ConnectionFailureException('Could not connect to PDO: ' . $e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
$this->setOption(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$this->dispatchEvent(new ConnectionEvent(DatabaseEvents::POST_CONNECT, $this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to escape a string for usage in an SQL statement.
|
||||
*
|
||||
* Oracle escaping reference:
|
||||
* http://www.orafaq.com/wiki/SQL_FAQ#How_does_one_escape_special_characters_when_writing_SQL_queries.3F
|
||||
*
|
||||
* SQLite escaping notes:
|
||||
* http://www.sqlite.org/faq.html#q14
|
||||
*
|
||||
* Method body is as implemented by the Zend Framework
|
||||
*
|
||||
* Note: Using query objects with bound variables is preferable to the below.
|
||||
*
|
||||
* @param string $text The string to be escaped.
|
||||
* @param boolean $extra Unused optional parameter to provide extra escaping.
|
||||
*
|
||||
* @return string The escaped string.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function escape($text, $extra = false)
|
||||
{
|
||||
if (\is_int($text)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
if (\is_float($text)) {
|
||||
// Force the dot as a decimal point.
|
||||
return str_replace(',', '.', (string) $text);
|
||||
}
|
||||
|
||||
$text = str_replace("'", "''", (string) $text);
|
||||
|
||||
return addcslashes($text, "\000\n\r\\\032");
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the SQL statement.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Take a local copy so that we don't modify the original query and cause issues later
|
||||
$sql = $this->replacePrefix((string) $this->sql);
|
||||
|
||||
// Increment the query counter.
|
||||
$this->count++;
|
||||
|
||||
// Get list of bounded parameters
|
||||
$bounded =& $this->sql->getBounded();
|
||||
|
||||
// If there is a monitor registered, let it know we are starting this query
|
||||
if ($this->monitor) {
|
||||
$this->monitor->startQuery($sql, $bounded);
|
||||
}
|
||||
|
||||
// Execute the query.
|
||||
$this->executed = false;
|
||||
|
||||
// Bind the variables
|
||||
foreach ($bounded as $key => $obj) {
|
||||
$this->statement->bindParam($key, $obj->value, $obj->dataType, $obj->length, $obj->driverOptions);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->executed = $this->statement->execute();
|
||||
|
||||
// If there is a monitor registered, let it know we have finished this query
|
||||
if ($this->monitor) {
|
||||
$this->monitor->stopQuery();
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (\PDOException $exception) {
|
||||
// If there is a monitor registered, let it know we have finished this query
|
||||
if ($this->monitor) {
|
||||
$this->monitor->stopQuery();
|
||||
}
|
||||
|
||||
// Get the error number and message before we execute any more queries.
|
||||
$errorNum = (int) $this->statement->errorCode();
|
||||
$errorMsg = (string) implode(', ', $this->statement->errorInfo());
|
||||
|
||||
// Check if the server was disconnected.
|
||||
try {
|
||||
if (!$this->connected()) {
|
||||
try {
|
||||
// Attempt to reconnect.
|
||||
$this->connection = null;
|
||||
$this->connect();
|
||||
} catch (ConnectionFailureException $e) {
|
||||
// If connect fails, ignore that exception and throw the normal exception.
|
||||
throw new ExecutionFailureException($sql, $errorMsg, $errorNum);
|
||||
}
|
||||
|
||||
// Since we were able to reconnect, run the query again.
|
||||
return $this->execute();
|
||||
}
|
||||
} catch (\LogicException $e) {
|
||||
throw new ExecutionFailureException($sql, $errorMsg, $errorNum, $e);
|
||||
}
|
||||
|
||||
// Throw the normal query exception.
|
||||
throw new ExecutionFailureException($sql, $errorMsg, $errorNum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a PDO database connection attribute
|
||||
* https://www.php.net/manual/en/pdo.getattribute.php
|
||||
*
|
||||
* Usage: $db->getOption(PDO::ATTR_CASE);
|
||||
*
|
||||
* @param mixed $key One of the PDO::ATTR_* Constants
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getOption($key)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return $this->connection->getAttribute($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the database connector.
|
||||
*
|
||||
* @return string The database connector version.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return $this->getOption(\PDO::ATTR_SERVER_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a query to run and verify the database is operational.
|
||||
*
|
||||
* @return string The query to check the health of the DB.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getConnectedQuery()
|
||||
{
|
||||
return 'SELECT 1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an attribute on the PDO database handle.
|
||||
* https://www.php.net/manual/en/pdo.setattribute.php
|
||||
*
|
||||
* Usage: $db->setOption(PDO::ATTR_CASE, PDO::CASE_UPPER);
|
||||
*
|
||||
* @param integer $key One of the PDO::ATTR_* Constants
|
||||
* @param mixed $value One of the associated PDO Constants
|
||||
* related to the particular attribute
|
||||
* key.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function setOption($key, $value)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return $this->connection->setAttribute($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the PDO extension is available.
|
||||
* Override as needed to check for specific PDO Drivers.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
return \defined('\\PDO::ATTR_DRIVER_NAME');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the connection to the server is active.
|
||||
*
|
||||
* @return boolean True if connected to the database engine.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function connected()
|
||||
{
|
||||
// Flag to prevent recursion into this function.
|
||||
static $checkingConnected = false;
|
||||
|
||||
if ($checkingConnected) {
|
||||
// Reset this flag and throw an exception.
|
||||
$checkingConnected = false;
|
||||
|
||||
throw new \LogicException('Recursion trying to check if connected.');
|
||||
}
|
||||
|
||||
// Backup the query state.
|
||||
$sql = $this->sql;
|
||||
$limit = $this->limit;
|
||||
$offset = $this->offset;
|
||||
$statement = $this->statement;
|
||||
|
||||
try {
|
||||
// Set the checking connection flag.
|
||||
$checkingConnected = true;
|
||||
|
||||
// Run a simple query to check the connection.
|
||||
$this->setQuery($this->getConnectedQuery());
|
||||
$status = (bool) $this->loadResult();
|
||||
} catch (\Exception $e) {
|
||||
// If we catch an exception here, we must not be connected.
|
||||
$status = false;
|
||||
}
|
||||
|
||||
// Restore the query state.
|
||||
$this->sql = $sql;
|
||||
$this->limit = $limit;
|
||||
$this->offset = $offset;
|
||||
$this->statement = $statement;
|
||||
$checkingConnected = false;
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the auto-incremented value from the last INSERT statement.
|
||||
*
|
||||
* @return string The value of the auto-increment field from the last inserted row.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function insertid()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Error suppress this to prevent PDO warning us that the driver doesn't support this operation.
|
||||
return @$this->connection->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a database for use.
|
||||
*
|
||||
* @param string $database The name of the database to select for use.
|
||||
*
|
||||
* @return boolean True if the database was successfully selected.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function select($database)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection to use UTF-8 character encoding.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function setUtf()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to commit a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, commit to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionCommit($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth === 1) {
|
||||
$this->connection->commit();
|
||||
}
|
||||
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to roll back a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, rollback to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionRollback($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth === 1) {
|
||||
$this->connection->rollBack();
|
||||
}
|
||||
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to initialize a transaction.
|
||||
*
|
||||
* @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionStart($asSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$asSavepoint || !$this->transactionDepth) {
|
||||
$this->connection->beginTransaction();
|
||||
}
|
||||
|
||||
$this->transactionDepth++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a SQL statement for execution
|
||||
*
|
||||
* @param string $query The SQL query to be prepared.
|
||||
*
|
||||
* @return StatementInterface
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws PrepareStatementFailureException
|
||||
*/
|
||||
protected function prepareStatement(string $query): StatementInterface
|
||||
{
|
||||
try {
|
||||
return new PdoStatement($this->connection->prepare($query, $this->options['driverOptions']));
|
||||
} catch (\PDOException $exception) {
|
||||
throw new PrepareStatementFailureException($exception->getMessage(), $exception->getCode(), $exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PDO does not support serialize
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
$serializedProperties = [];
|
||||
|
||||
$reflect = new \ReflectionClass($this);
|
||||
|
||||
// Get properties of the current class
|
||||
$properties = $reflect->getProperties();
|
||||
|
||||
foreach ($properties as $property) {
|
||||
// Do not serialize properties that are PDO
|
||||
if ($property->isStatic() === false && !($this->{$property->name} instanceof \PDO)) {
|
||||
$serializedProperties[] = $property->name;
|
||||
}
|
||||
}
|
||||
|
||||
return $serializedProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wake up after serialization
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
// Get connection back
|
||||
$this->__construct($this->options);
|
||||
}
|
||||
}
|
||||
53
libraries/vendor/joomla/database/src/Pdo/PdoQuery.php
vendored
Normal file
53
libraries/vendor/joomla/database/src/Pdo/PdoQuery.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Pdo;
|
||||
|
||||
use Joomla\Database\DatabaseQuery;
|
||||
|
||||
/**
|
||||
* PDO Query Building Class.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
abstract class PdoQuery extends DatabaseQuery
|
||||
{
|
||||
/**
|
||||
* The list of zero or null representation of a datetime.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $nullDatetimeList = ['0000-00-00 00:00:00'];
|
||||
|
||||
/**
|
||||
* Casts a value to a char.
|
||||
*
|
||||
* Ensure that the value is properly quoted before passing to the method.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->castAsChar('a'));
|
||||
* $query->select($query->castAsChar('a', 40));
|
||||
*
|
||||
* @param string $value The value to cast as a char.
|
||||
* @param string $len The length of the char.
|
||||
*
|
||||
* @return string Returns the cast value.
|
||||
*
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public function castAsChar($value, $len = null)
|
||||
{
|
||||
if (!$len) {
|
||||
return $value;
|
||||
} else {
|
||||
return 'CAST(' . $value . ' AS CHAR(' . $len . '))';
|
||||
}
|
||||
}
|
||||
}
|
||||
243
libraries/vendor/joomla/database/src/Pdo/PdoStatement.php
vendored
Normal file
243
libraries/vendor/joomla/database/src/Pdo/PdoStatement.php
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Pdo;
|
||||
|
||||
use Joomla\Database\FetchMode;
|
||||
use Joomla\Database\FetchOrientation;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Database\StatementInterface;
|
||||
|
||||
/**
|
||||
* PDO Database Statement.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class PdoStatement implements StatementInterface
|
||||
{
|
||||
/**
|
||||
* Mapping array for fetch modes.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private const FETCH_MODE_MAP = [
|
||||
FetchMode::ASSOCIATIVE => \PDO::FETCH_ASSOC,
|
||||
FetchMode::NUMERIC => \PDO::FETCH_NUM,
|
||||
FetchMode::MIXED => \PDO::FETCH_BOTH,
|
||||
FetchMode::STANDARD_OBJECT => \PDO::FETCH_OBJ,
|
||||
FetchMode::COLUMN => \PDO::FETCH_COLUMN,
|
||||
FetchMode::CUSTOM_OBJECT => \PDO::FETCH_CLASS,
|
||||
];
|
||||
|
||||
/**
|
||||
* Mapping array for parameter types.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private const PARAMETER_TYPE_MAP = [
|
||||
ParameterType::BOOLEAN => \PDO::PARAM_BOOL,
|
||||
ParameterType::INTEGER => \PDO::PARAM_INT,
|
||||
ParameterType::LARGE_OBJECT => \PDO::PARAM_LOB,
|
||||
ParameterType::NULL => \PDO::PARAM_NULL,
|
||||
ParameterType::STRING => \PDO::PARAM_STR,
|
||||
];
|
||||
|
||||
/**
|
||||
* The decorated PDOStatement object.
|
||||
*
|
||||
* @var \PDOStatement
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $pdoStatement;
|
||||
|
||||
/**
|
||||
* Statement constructor
|
||||
*
|
||||
* @param \PDOStatement $pdoStatement The decorated PDOStatement object.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __construct(\PDOStatement $pdoStatement)
|
||||
{
|
||||
$this->pdoStatement = $pdoStatement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a parameter to the specified variable name.
|
||||
*
|
||||
* @param string|integer $parameter Parameter identifier. For a prepared statement using named placeholders, this will be a parameter
|
||||
* name of the form `:name`. For a prepared statement using question mark placeholders, this will be
|
||||
* the 1-indexed position of the parameter.
|
||||
* @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter.
|
||||
* @param string $dataType Constant corresponding to a SQL datatype, this should be the processed type from the QueryInterface.
|
||||
* @param integer $length The length of the variable. Usually required for OUTPUT parameters.
|
||||
* @param array $driverOptions Optional driver options to be used.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function bindParam($parameter, &$variable, string $dataType = ParameterType::STRING, ?int $length = null, ?array $driverOptions = null)
|
||||
{
|
||||
$type = $this->convertParameterType($dataType);
|
||||
$extraParameters = array_slice(func_get_args(), 3);
|
||||
|
||||
if (count($extraParameters) !== 0) {
|
||||
$extraParameters[0] = $extraParameters[0] ?? 0;
|
||||
}
|
||||
|
||||
$this->pdoStatement->bindParam($parameter, $variable, $type, ...$extraParameters);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the cursor, enabling the statement to be executed again.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function closeCursor(): void
|
||||
{
|
||||
$this->pdoStatement->closeCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the SQLSTATE associated with the last operation on the statement handle.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function errorCode()
|
||||
{
|
||||
return $this->pdoStatement->errorCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches extended error information associated with the last operation on the statement handle.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function errorInfo()
|
||||
{
|
||||
return $this->pdoStatement->errorInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a prepared statement
|
||||
*
|
||||
* @param array|null $parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function execute(?array $parameters = null)
|
||||
{
|
||||
return $this->pdoStatement->execute($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the next row from a result set
|
||||
*
|
||||
* @param integer|null $fetchStyle Controls how the next row will be returned to the caller. This value must be one of the
|
||||
* FetchMode constants, defaulting to value of FetchMode::MIXED.
|
||||
* @param integer $cursorOrientation For a StatementInterface object representing a scrollable cursor, this value determines which row
|
||||
* will be returned to the caller. This value must be one of the FetchOrientation constants,
|
||||
* defaulting to FetchOrientation::NEXT.
|
||||
* @param integer $cursorOffset For a StatementInterface object representing a scrollable cursor for which the cursorOrientation
|
||||
* parameter is set to FetchOrientation::ABS, this value specifies the absolute number of the row in
|
||||
* the result set that shall be fetched. For a StatementInterface object representing a scrollable
|
||||
* cursor for which the cursorOrientation parameter is set to FetchOrientation::REL, this value
|
||||
* specifies the row to fetch relative to the cursor position before `fetch()` was called.
|
||||
*
|
||||
* @return mixed The return value of this function on success depends on the fetch type. In all cases, boolean false is returned on failure.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function fetch(?int $fetchStyle = null, int $cursorOrientation = FetchOrientation::NEXT, int $cursorOffset = 0)
|
||||
{
|
||||
if ($fetchStyle === null) {
|
||||
return $this->pdoStatement->fetch();
|
||||
}
|
||||
|
||||
return $this->pdoStatement->fetch($this->convertFetchMode($fetchStyle), $cursorOrientation, $cursorOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of rows affected by the last SQL statement.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function rowCount(): int
|
||||
{
|
||||
return $this->pdoStatement->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fetch mode to use while iterating this statement.
|
||||
*
|
||||
* @param integer $fetchMode The fetch mode, must be one of the FetchMode constants.
|
||||
* @param mixed ...$args Optional mode-specific arguments.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function setFetchMode(int $fetchMode, ...$args): void
|
||||
{
|
||||
$this->pdoStatement->setFetchMode($this->convertFetchMode($fetchMode), ...$args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the database API's fetch mode to a PDO fetch mode
|
||||
*
|
||||
* @param integer $mode Fetch mode to convert
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \InvalidArgumentException if the fetch mode is unsupported
|
||||
*/
|
||||
private function convertFetchMode(int $mode): int
|
||||
{
|
||||
if (!isset(self::FETCH_MODE_MAP[$mode])) {
|
||||
throw new \InvalidArgumentException(sprintf('Unsupported fetch mode `%s`', $mode));
|
||||
}
|
||||
|
||||
return self::FETCH_MODE_MAP[$mode];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the database API's parameter type to a PDO parameter type
|
||||
*
|
||||
* @param string $type Parameter type to convert
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \InvalidArgumentException if the parameter type is unsupported
|
||||
*/
|
||||
private function convertParameterType(string $type): int
|
||||
{
|
||||
if (!isset(self::PARAMETER_TYPE_MAP[$type])) {
|
||||
throw new \InvalidArgumentException(sprintf('Unsupported parameter type `%s`', $type));
|
||||
}
|
||||
|
||||
return self::PARAMETER_TYPE_MAP[$type];
|
||||
}
|
||||
}
|
||||
1066
libraries/vendor/joomla/database/src/Pgsql/PgsqlDriver.php
vendored
Normal file
1066
libraries/vendor/joomla/database/src/Pgsql/PgsqlDriver.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
184
libraries/vendor/joomla/database/src/Pgsql/PgsqlExporter.php
vendored
Normal file
184
libraries/vendor/joomla/database/src/Pgsql/PgsqlExporter.php
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Pgsql;
|
||||
|
||||
use Joomla\Database\DatabaseExporter;
|
||||
|
||||
/**
|
||||
* PDO PostgreSQL Database Exporter.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class PgsqlExporter extends DatabaseExporter
|
||||
{
|
||||
/**
|
||||
* Builds the XML data for the tables to export.
|
||||
*
|
||||
* @return string An XML string
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXml()
|
||||
{
|
||||
$buffer = [];
|
||||
|
||||
$buffer[] = '<?xml version="1.0"?>';
|
||||
$buffer[] = '<postgresqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
|
||||
$buffer[] = ' <database name="">';
|
||||
|
||||
if ($this->options->withStructure) {
|
||||
$buffer = array_merge($buffer, $this->buildXmlStructure());
|
||||
}
|
||||
|
||||
if ($this->options->withData) {
|
||||
$buffer = array_merge($buffer, $this->buildXmlData());
|
||||
}
|
||||
|
||||
$buffer[] = ' </database>';
|
||||
$buffer[] = '</postgresqldump>';
|
||||
|
||||
return implode("\n", $buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XML structure to export.
|
||||
*
|
||||
* @return array An array of XML lines (strings).
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXmlStructure()
|
||||
{
|
||||
$buffer = [];
|
||||
|
||||
foreach ($this->from as $table) {
|
||||
// Replace the magic prefix if found.
|
||||
$table = $this->getGenericTableName($table);
|
||||
|
||||
// Get the details columns information.
|
||||
$fields = $this->db->getTableColumns($table, false);
|
||||
$keys = $this->db->getTableKeys($table);
|
||||
$sequences = $this->db->getTableSequences($table);
|
||||
|
||||
$buffer[] = ' <table_structure name="' . $table . '">';
|
||||
|
||||
foreach ($sequences as $sequence) {
|
||||
$buffer[] = ' <sequence Name="' . $this->getGenericTableName($sequence->sequence) . '" Schema="' . $sequence->schema . '"' .
|
||||
' Table="' . $table . '" Column="' . $sequence->column . '" Type="' . $sequence->data_type . '"' .
|
||||
' Start_Value="' . $sequence->start_value . '" Min_Value="' . $sequence->minimum_value . '"' .
|
||||
' Max_Value="' . $sequence->maximum_value . '" Last_Value="' . $this->db->getSequenceLastValue($sequence->sequence) . '"' .
|
||||
' Increment="' . $sequence->increment . '" Cycle_option="' . $sequence->cycle_option . '"' .
|
||||
' Is_called="' . $this->db->getSequenceIsCalled($sequence->sequence) . '"' .
|
||||
' />';
|
||||
}
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$buffer[] = ' <field Field="' . $field->column_name . '" Type="' . $field->type . '" Null="' . $field->null . '"' .
|
||||
' Default="' . $field->Default . '" Comments="' . $field->comments . '" />';
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$buffer[] = ' <key Index="' . $this->getGenericTableName($key->idxName) . '" is_primary="' . $key->isPrimary . '"' .
|
||||
' is_unique="' . $key->isUnique . '" Key_name="' . $this->db->getNamesKey($table, $key->indKey) . '"' .
|
||||
' Query=\'' . $key->Query . '\' />';
|
||||
}
|
||||
|
||||
$buffer[] = ' </table_structure>';
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XML data to export.
|
||||
*
|
||||
* @return array An array of XML lines (strings).
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXmlData()
|
||||
{
|
||||
$buffer = [];
|
||||
|
||||
foreach ($this->from as $table) {
|
||||
// Replace the magic prefix if found.
|
||||
$table = $this->getGenericTableName($table);
|
||||
|
||||
// Get the details columns information.
|
||||
$fields = $this->db->getTableColumns($table, false);
|
||||
$colblob = [];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
// Catch blob for xml conversion
|
||||
// PostgreSQL binary large object type
|
||||
if ($field->Type == 'bytea') {
|
||||
$colblob[] = $field->Field;
|
||||
}
|
||||
}
|
||||
|
||||
$query = $this->db->getQuery(true);
|
||||
$query->select($query->quoteName(array_keys($fields)))
|
||||
->from($query->quoteName($table));
|
||||
$this->db->setQuery($query);
|
||||
|
||||
$rows = $this->db->loadObjectList();
|
||||
|
||||
if (!count($rows)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$buffer[] = ' <table_data name="' . $table . '">';
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$buffer[] = ' <row>';
|
||||
|
||||
foreach ($row as $key => $value) {
|
||||
if (!in_array($key, $colblob)) {
|
||||
$buffer[] = ' <field name="' . $key . '">' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</field>';
|
||||
} else {
|
||||
$buffer[] = ' <field name="' . $key . '">' . stream_get_contents($value) . '</field>';
|
||||
}
|
||||
}
|
||||
|
||||
$buffer[] = ' </row>';
|
||||
}
|
||||
|
||||
$buffer[] = ' </table_data>';
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all data and options are in order prior to exporting.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.5.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
// Check if the db connector has been set.
|
||||
if (!($this->db instanceof PgsqlDriver)) {
|
||||
throw new \RuntimeException('Database connection wrong type.');
|
||||
}
|
||||
|
||||
// Check if the tables have been specified.
|
||||
if (empty($this->from)) {
|
||||
throw new \RuntimeException('ERROR: No Tables Specified');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
555
libraries/vendor/joomla/database/src/Pgsql/PgsqlImporter.php
vendored
Normal file
555
libraries/vendor/joomla/database/src/Pgsql/PgsqlImporter.php
vendored
Normal file
@ -0,0 +1,555 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Pgsql;
|
||||
|
||||
use Joomla\Database\DatabaseImporter;
|
||||
|
||||
/**
|
||||
* PDO PostgreSQL Database Importer.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class PgsqlImporter extends DatabaseImporter
|
||||
{
|
||||
/**
|
||||
* Checks if all data and options are in order prior to exporting.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.5.0
|
||||
* @throws \RuntimeException if an error is encountered.
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
// Check if the db connector has been set.
|
||||
if (!($this->db instanceof PgsqlDriver)) {
|
||||
throw new \RuntimeException('Database connection wrong type.');
|
||||
}
|
||||
|
||||
// Check if the tables have been specified.
|
||||
if (empty($this->from)) {
|
||||
throw new \RuntimeException('ERROR: No Tables Specified');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add an index.
|
||||
*
|
||||
* @param \SimpleXMLElement $field The XML index definition.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getAddIndexSql(\SimpleXMLElement $field)
|
||||
{
|
||||
return (string) $field['Query'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alters for table if there is a difference.
|
||||
*
|
||||
* @param \SimpleXMLElement $structure The XML structure of the table.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getAlterTableSql(\SimpleXMLElement $structure)
|
||||
{
|
||||
$table = $this->getRealTableName($structure['name']);
|
||||
$oldFields = $this->db->getTableColumns($table);
|
||||
$oldKeys = $this->db->getTableKeys($table);
|
||||
$oldSequence = $this->db->getTableSequences($table);
|
||||
$alters = [];
|
||||
|
||||
// Get the fields and keys from the XML that we are aiming for.
|
||||
$newFields = $structure->xpath('field');
|
||||
$newKeys = $structure->xpath('key');
|
||||
$newSequence = $structure->xpath('sequence');
|
||||
|
||||
/*
|
||||
* Sequence section
|
||||
*/
|
||||
|
||||
$oldSeq = $this->getSeqLookup($oldSequence);
|
||||
$newSequenceLook = $this->getSeqLookup($newSequence);
|
||||
|
||||
foreach ($newSequenceLook as $kSeqName => $vSeq) {
|
||||
if (isset($oldSeq[$kSeqName])) {
|
||||
// The field exists, check it's the same.
|
||||
$column = $oldSeq[$kSeqName][0];
|
||||
|
||||
// Test whether there is a change.
|
||||
$change = ((string) $vSeq[0]['Type'] !== $column->Type)
|
||||
|| ((string) $vSeq[0]['Start_Value'] !== $column->Start_Value)
|
||||
|| ((string) $vSeq[0]['Min_Value'] !== $column->Min_Value)
|
||||
|| ((string) $vSeq[0]['Max_Value'] !== $column->Max_Value)
|
||||
|| ((string) $vSeq[0]['Increment'] !== $column->Increment)
|
||||
|| ((string) $vSeq[0]['Cycle_option'] !== $column->Cycle_option)
|
||||
|| ((string) $vSeq[0]['Table'] !== $column->Table)
|
||||
|| ((string) $vSeq[0]['Column'] !== $column->Column)
|
||||
|| ((string) $vSeq[0]['Schema'] !== $column->Schema)
|
||||
|| ((string) $vSeq[0]['Name'] !== $column->Name);
|
||||
|
||||
if ($change) {
|
||||
$alters[] = $this->getChangeSequenceSql($kSeqName, $vSeq);
|
||||
$alters[] = $this->getSetvalSequenceSql($kSeqName, $vSeq);
|
||||
}
|
||||
|
||||
// Unset this field so that what we have left are fields that need to be removed.
|
||||
unset($oldSeq[$kSeqName]);
|
||||
} else {
|
||||
// The sequence is new
|
||||
$alters[] = $this->getAddSequenceSql($newSequenceLook[$kSeqName][0]);
|
||||
$alters[] = $this->getSetvalSequenceSql($newSequenceLook[$kSeqName][0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Any sequences left are orphans
|
||||
foreach ($oldSeq as $name => $column) {
|
||||
// Delete the sequence.
|
||||
$alters[] = $this->getDropSequenceSql($name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Field section
|
||||
*/
|
||||
|
||||
// Loop through each field in the new structure.
|
||||
foreach ($newFields as $field) {
|
||||
$fName = (string) $field['Field'];
|
||||
|
||||
if (isset($oldFields[$fName])) {
|
||||
// The field exists, check it's the same.
|
||||
$column = $oldFields[$fName];
|
||||
|
||||
// Test whether there is a change.
|
||||
$change = ((string) $field['Type'] !== $column->Type) || ((string) $field['Null'] !== $column->Null)
|
||||
|| ((string) $field['Default'] !== $column->Default);
|
||||
|
||||
if ($change) {
|
||||
$alters[] = $this->getChangeColumnSql($table, $field);
|
||||
}
|
||||
|
||||
// Unset this field so that what we have left are fields that need to be removed.
|
||||
unset($oldFields[$fName]);
|
||||
} else {
|
||||
// The field is new.
|
||||
$alters[] = $this->getAddColumnSql($table, $field);
|
||||
}
|
||||
}
|
||||
|
||||
// Any columns left are orphans
|
||||
foreach ($oldFields as $name => $column) {
|
||||
// Delete the column.
|
||||
$alters[] = $this->getDropColumnSql($table, $name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Index section
|
||||
*/
|
||||
|
||||
// Get the lookups for the old and new keys
|
||||
$oldLookup = $this->getKeyLookup($oldKeys);
|
||||
$newLookup = $this->getKeyLookup($newKeys);
|
||||
|
||||
// Loop through each key in the new structure.
|
||||
foreach ($newLookup as $name => $keys) {
|
||||
// Check if there are keys on this field in the existing table.
|
||||
if (isset($oldLookup[$name])) {
|
||||
$same = true;
|
||||
$newCount = \count($newLookup[$name]);
|
||||
$oldCount = \count($oldLookup[$name]);
|
||||
|
||||
// There is a key on this field in the old and new tables. Are they the same?
|
||||
if ($newCount === $oldCount) {
|
||||
for ($i = 0; $i < $newCount; $i++) {
|
||||
// Check only query field -> different query means different index
|
||||
$same = ((string) $newLookup[$name][$i]['Query'] === $oldLookup[$name][$i]->Query);
|
||||
|
||||
if (!$same) {
|
||||
// Break out of the loop. No need to check further.
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Count is different, just drop and add.
|
||||
$same = false;
|
||||
}
|
||||
|
||||
if (!$same) {
|
||||
$alters[] = $this->getDropIndexSql($name);
|
||||
$alters[] = (string) $newLookup[$name][0]['Query'];
|
||||
}
|
||||
|
||||
// Unset this field so that what we have left are fields that need to be removed.
|
||||
unset($oldLookup[$name]);
|
||||
} else {
|
||||
// This is a new key.
|
||||
$alters[] = (string) $newLookup[$name][0]['Query'];
|
||||
}
|
||||
}
|
||||
|
||||
// Any keys left are orphans.
|
||||
foreach ($oldLookup as $name => $keys) {
|
||||
if ($oldLookup[$name][0]->is_primary === 'TRUE') {
|
||||
$alters[] = $this->getDropPrimaryKeySql($table, $oldLookup[$name][0]->Index);
|
||||
} else {
|
||||
$alters[] = $this->getDropIndexSql($name);
|
||||
}
|
||||
}
|
||||
|
||||
return $alters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a sequence.
|
||||
*
|
||||
* @param string $name The name of the sequence to drop.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getDropSequenceSql($name)
|
||||
{
|
||||
return 'DROP SEQUENCE ' . $this->db->quoteName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the syntax to add a sequence.
|
||||
*
|
||||
* @param \SimpleXMLElement $field The XML definition for the sequence.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getAddSequenceSql(\SimpleXMLElement $field)
|
||||
{
|
||||
$sql = 'CREATE SEQUENCE IF NOT EXISTS ' . (string) $field['Name']
|
||||
. ' INCREMENT BY ' . (string) $field['Increment'] . ' MINVALUE ' . $field['Min_Value']
|
||||
. ' MAXVALUE ' . (string) $field['Max_Value'] . ' START ' . (string) $field['Start_Value']
|
||||
. (((string) $field['Cycle_option'] === 'NO') ? ' NO' : '') . ' CYCLE'
|
||||
. ' OWNED BY ' . $this->db->quoteName((string) $field['Schema'] . '.' . (string) $field['Table'] . '.' . (string) $field['Column']);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the syntax to alter a sequence.
|
||||
*
|
||||
* @param \SimpleXMLElement $field The XML definition for the sequence.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getChangeSequenceSql(\SimpleXMLElement $field)
|
||||
{
|
||||
$sql = 'ALTER SEQUENCE ' . (string) $field['Name']
|
||||
. ' INCREMENT BY ' . (string) $field['Increment'] . ' MINVALUE ' . (string) $field['Min_Value']
|
||||
. ' MAXVALUE ' . (string) $field['Max_Value'] . ' START ' . (string) $field['Start_Value']
|
||||
. ' OWNED BY ' . $this->db->quoteName((string) $field['Schema'] . '.' . (string) $field['Table'] . '.' . (string) $field['Column']);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the syntax to setval a sequence.
|
||||
*
|
||||
* @param \SimpleXMLElement $field The XML definition for the sequence.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected function getSetvalSequenceSql($field)
|
||||
{
|
||||
$is_called = $field['Is_called'] == 't' || $field['Is_called'] == '1' ? 'TRUE' : 'FALSE';
|
||||
|
||||
return 'SELECT setval(\'' . (string) $field['Name'] . '\', ' . (string) $field['Last_Value'] . ', ' . $is_called . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the syntax to alter a column.
|
||||
*
|
||||
* @param string $table The name of the database table to alter.
|
||||
* @param \SimpleXMLElement $field The XML definition for the field.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getChangeColumnSql($table, \SimpleXMLElement $field)
|
||||
{
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' ALTER COLUMN ' . $this->db->quoteName((string) $field['Field']) . ' '
|
||||
. $this->getAlterColumnSql($table, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax for a single column that would be included in a table create statement.
|
||||
*
|
||||
* @param string $table The name of the database table to alter.
|
||||
* @param \SimpleXMLElement $field The XML field definition.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getAlterColumnSql($table, \SimpleXMLElement $field)
|
||||
{
|
||||
// TODO Incorporate into parent class and use $this.
|
||||
$blobs = ['text', 'smalltext', 'mediumtext', 'largetext'];
|
||||
|
||||
$fName = (string) $field['Field'];
|
||||
$fType = (string) $field['Type'];
|
||||
$fNull = (string) $field['Null'];
|
||||
|
||||
$fDefault = (isset($field['Default']) && $field['Default'] != 'NULL') ?
|
||||
preg_match('/^[0-9]$/', $field['Default']) ? $field['Default'] : $this->db->quote((string) $field['Default'])
|
||||
: null;
|
||||
|
||||
$sql = ' TYPE ' . $fType;
|
||||
|
||||
if ($fNull === 'NO') {
|
||||
if ($fDefault === null || \in_array($fType, $blobs, true)) {
|
||||
$sql .= ",\nALTER COLUMN " . $this->db->quoteName($fName) . ' SET NOT NULL'
|
||||
. ",\nALTER COLUMN " . $this->db->quoteName($fName) . ' DROP DEFAULT';
|
||||
} else {
|
||||
$sql .= ",\nALTER COLUMN " . $this->db->quoteName($fName) . ' SET NOT NULL'
|
||||
. ",\nALTER COLUMN " . $this->db->quoteName($fName) . ' SET DEFAULT ' . $fDefault;
|
||||
}
|
||||
} else {
|
||||
if ($fDefault !== null) {
|
||||
$sql .= ",\nALTER COLUMN " . $this->db->quoteName($fName) . ' DROP NOT NULL'
|
||||
. ",\nALTER COLUMN " . $this->db->quoteName($fName) . ' SET DEFAULT ' . $fDefault;
|
||||
}
|
||||
}
|
||||
|
||||
// Sequence was created in other function, here is associated a default value but not yet owner
|
||||
if (strpos($fDefault, 'nextval') !== false) {
|
||||
$sequence = $table . '_' . $fName . '_seq';
|
||||
$owner = $table . '.' . $fName;
|
||||
|
||||
$sql .= ";\nALTER SEQUENCE " . $this->db->quoteName($sequence) . ' OWNED BY ' . $this->db->quoteName($owner);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax for a single column that would be included in a table create statement.
|
||||
*
|
||||
* @param \SimpleXMLElement $field The XML field definition.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getColumnSql(\SimpleXMLElement $field)
|
||||
{
|
||||
$fName = (string) $field['Field'];
|
||||
$fType = (string) $field['Type'];
|
||||
$fNull = (string) $field['Null'];
|
||||
|
||||
if (strpos($field['Default'], '::') != false) {
|
||||
$fDefault = strstr($field['Default'], '::', true);
|
||||
} else {
|
||||
$fDefault = isset($field['Default']) && strlen($field['Default']) > 0
|
||||
? preg_match('/^[0-9]$/', $field['Default']) ? $field['Default'] : $this->db->quote((string) $field['Default'])
|
||||
: null;
|
||||
}
|
||||
|
||||
// Note, nextval() as default value means that type field is serial.
|
||||
if (strpos($fDefault, 'nextval') !== false) {
|
||||
$sql = $this->db->quoteName($fName) . ' SERIAL';
|
||||
} else {
|
||||
$sql = $this->db->quoteName($fName) . ' ' . $fType;
|
||||
|
||||
if ($fNull == 'NO') {
|
||||
if ($fDefault === null) {
|
||||
$sql .= ' NOT NULL';
|
||||
} else {
|
||||
$sql .= ' NOT NULL DEFAULT ' . $fDefault;
|
||||
}
|
||||
} else {
|
||||
if ($fDefault !== null) {
|
||||
$sql .= ' DEFAULT ' . $fDefault;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop an index.
|
||||
*
|
||||
* @param string $name The name of the key to drop.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getDropIndexSql($name)
|
||||
{
|
||||
return 'DROP INDEX ' . $this->db->quoteName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param string $name The constraint name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getDropPrimaryKeySql($table, $name)
|
||||
{
|
||||
return 'ALTER TABLE ONLY ' . $this->db->quoteName($table) . ' DROP CONSTRAINT ' . $this->db->quoteName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of keys for a table.
|
||||
*
|
||||
* @param array $keys An array of objects that comprise the keys for the table.
|
||||
*
|
||||
* @return array The lookup array. array({key name} => array(object, ...))
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
protected function getKeyLookup($keys)
|
||||
{
|
||||
// First pass, create a lookup of the keys.
|
||||
$lookup = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if ($key instanceof \SimpleXMLElement) {
|
||||
$kName = (string) $key['Index'];
|
||||
} else {
|
||||
$kName = $key->Index;
|
||||
}
|
||||
|
||||
if (empty($lookup[$kName])) {
|
||||
$lookup[$kName] = [];
|
||||
}
|
||||
|
||||
$lookup[$kName][] = $key;
|
||||
}
|
||||
|
||||
return $lookup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add a unique constraint for a table key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param array $key The key.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected function getAddUniqueSql($table, $key)
|
||||
{
|
||||
if ($key instanceof \SimpleXMLElement) {
|
||||
$kName = (string) $key['Key_name'];
|
||||
$kIndex = (string) $key['Index'];
|
||||
} else {
|
||||
$kName = $key->Key_name;
|
||||
$kIndex = $key->Index;
|
||||
}
|
||||
|
||||
$unique = $kIndex . ' UNIQUE (' . $kName . ')';
|
||||
|
||||
return 'ALTER TABLE ' . $this->db->quoteName($table) . ' ADD CONSTRAINT ' . $unique;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of sequences for a table.
|
||||
*
|
||||
* @param array $sequences An array of objects that comprise the sequences for the table.
|
||||
*
|
||||
* @return array The lookup array. array({key name} => array(object, ...))
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getSeqLookup($sequences)
|
||||
{
|
||||
// First pass, create a lookup of the keys.
|
||||
$lookup = [];
|
||||
|
||||
foreach ($sequences as $seq) {
|
||||
if ($seq instanceof \SimpleXMLElement) {
|
||||
$sName = (string) $seq['Name'];
|
||||
} else {
|
||||
$sName = $seq->Name;
|
||||
}
|
||||
|
||||
if (empty($lookup[$sName])) {
|
||||
$lookup[$sName] = [];
|
||||
}
|
||||
|
||||
$lookup[$sName][] = $seq;
|
||||
}
|
||||
|
||||
return $lookup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add a table.
|
||||
*
|
||||
* @param \SimpleXMLElement $table The table information.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function xmlToCreate(\SimpleXMLElement $table)
|
||||
{
|
||||
$existingTables = $this->db->getTableList();
|
||||
$tableName = (string) $table['name'];
|
||||
|
||||
if (in_array($tableName, $existingTables)) {
|
||||
throw new \RuntimeException('The table you are trying to create already exists');
|
||||
}
|
||||
|
||||
$createTableStatement = 'CREATE TABLE ' . $this->db->quoteName($tableName) . ' (';
|
||||
|
||||
foreach ($table->xpath('field') as $field) {
|
||||
$createTableStatement .= $this->getColumnSql($field) . ', ';
|
||||
}
|
||||
|
||||
$createTableStatement = rtrim($createTableStatement, ', ');
|
||||
$createTableStatement .= ');';
|
||||
|
||||
foreach ($table->xpath('sequence') as $seq) {
|
||||
$createTableStatement .= $this->getAddSequenceSql($seq) . ';';
|
||||
$createTableStatement .= $this->getSetvalSequenceSql($seq) . ';';
|
||||
}
|
||||
|
||||
foreach ($table->xpath('key') as $key) {
|
||||
if ((($key['is_primary'] == 'f') || ($key['is_primary'] == '')) && (($key['is_unique'] == 't') || ($key['is_unique'] == '1'))) {
|
||||
$createTableStatement .= $this->getAddUniqueSql($tableName, $key) . ';';
|
||||
} else {
|
||||
$createTableStatement .= $this->getAddIndexSql($key) . ';';
|
||||
}
|
||||
}
|
||||
|
||||
return $createTableStatement;
|
||||
}
|
||||
}
|
||||
62
libraries/vendor/joomla/database/src/Pgsql/PgsqlQuery.php
vendored
Normal file
62
libraries/vendor/joomla/database/src/Pgsql/PgsqlQuery.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Pgsql;
|
||||
|
||||
use Joomla\Database\Pdo\PdoQuery;
|
||||
use Joomla\Database\Query\PostgresqlQueryBuilder;
|
||||
use Joomla\Database\Query\QueryElement;
|
||||
|
||||
/**
|
||||
* PDO PostgreSQL Query Building Class.
|
||||
*
|
||||
* @since 1.0
|
||||
*
|
||||
* @property-read QueryElement $forUpdate The FOR UPDATE element used in "FOR UPDATE" lock
|
||||
* @property-read QueryElement $forShare The FOR SHARE element used in "FOR SHARE" lock
|
||||
* @property-read QueryElement $noWait The NOWAIT element used in "FOR SHARE" and "FOR UPDATE" lock
|
||||
* @property-read QueryElement $returning The RETURNING element of INSERT INTO
|
||||
*/
|
||||
class PgsqlQuery extends PdoQuery
|
||||
{
|
||||
use PostgresqlQueryBuilder;
|
||||
|
||||
/**
|
||||
* The list of zero or null representation of a datetime.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $nullDatetimeList = ['1970-01-01 00:00:00'];
|
||||
|
||||
/**
|
||||
* Casts a value to a char.
|
||||
*
|
||||
* Ensure that the value is properly quoted before passing to the method.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->castAsChar('a'));
|
||||
* $query->select($query->castAsChar('a', 40));
|
||||
*
|
||||
* @param string $value The value to cast as a char.
|
||||
* @param string $length The length of the char.
|
||||
*
|
||||
* @return string Returns the cast value.
|
||||
*
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public function castAsChar($value, $length = null)
|
||||
{
|
||||
if ((int) $length < 1) {
|
||||
return $value . '::text';
|
||||
}
|
||||
|
||||
return 'CAST(' . $value . ' AS CHAR(' . $length . '))';
|
||||
}
|
||||
}
|
||||
61
libraries/vendor/joomla/database/src/Query/LimitableInterface.php
vendored
Normal file
61
libraries/vendor/joomla/database/src/Query/LimitableInterface.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Query;
|
||||
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
trigger_deprecation(
|
||||
'joomla/database',
|
||||
'2.0.0',
|
||||
'%s() is deprecated and will be removed in 3.0, all query objects should implement %s instead.',
|
||||
LimitableInterface::class,
|
||||
QueryInterface::class
|
||||
);
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Joomla Database Query LimitableInterface.
|
||||
*
|
||||
* @since 1.0
|
||||
* @deprecated 3.0 Capabilities will be required in Joomla\Database\QueryInterface
|
||||
*/
|
||||
interface LimitableInterface
|
||||
{
|
||||
/**
|
||||
* Method to modify a query already in string format with the needed additions to make the query limited to a particular number of
|
||||
* results, or start at a particular offset.
|
||||
*
|
||||
* @param string $query The query in string format
|
||||
* @param integer $limit The limit for the result set
|
||||
* @param integer $offset The offset for the result set
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function processLimit($query, $limit, $offset = 0);
|
||||
|
||||
/**
|
||||
* Sets the offset and limit for the result set, if the database driver supports it.
|
||||
*
|
||||
* Usage:
|
||||
* $query->setLimit(100, 0); (retrieve 100 rows, starting at first record)
|
||||
* $query->setLimit(50, 50); (retrieve 50 rows, starting at 50th record)
|
||||
*
|
||||
* @param integer $limit The limit for the result set
|
||||
* @param integer $offset The offset for the result set
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function setLimit($limit = 0, $offset = 0);
|
||||
}
|
||||
254
libraries/vendor/joomla/database/src/Query/MysqlQueryBuilder.php
vendored
Normal file
254
libraries/vendor/joomla/database/src/Query/MysqlQueryBuilder.php
vendored
Normal file
@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Query;
|
||||
|
||||
/**
|
||||
* Trait for MySQL Query Building.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
trait MysqlQueryBuilder
|
||||
{
|
||||
/**
|
||||
* Magic function to convert the query to a string.
|
||||
*
|
||||
* @return string The completed query.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
switch ($this->type) {
|
||||
case 'select':
|
||||
if ($this->selectRowNumber) {
|
||||
$orderBy = $this->selectRowNumber['orderBy'];
|
||||
$tmpOffset = $this->offset;
|
||||
$tmpLimit = $this->limit;
|
||||
$this->offset = 0;
|
||||
$this->limit = 0;
|
||||
$tmpOrder = $this->order;
|
||||
$this->order = null;
|
||||
$query = parent::__toString();
|
||||
$this->order = $tmpOrder;
|
||||
$this->offset = $tmpOffset;
|
||||
$this->limit = $tmpLimit;
|
||||
|
||||
// Add support for second order by, offset and limit
|
||||
$query = PHP_EOL . 'SELECT * FROM (' . $query . PHP_EOL . "ORDER BY $orderBy" . PHP_EOL . ') w';
|
||||
|
||||
if ($this->order) {
|
||||
$query .= (string) $this->order;
|
||||
}
|
||||
|
||||
return $this->processLimit($query, $this->limit, $this->offset);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::__toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to modify a query already in string format with the needed additions to make the query limited to a particular number of
|
||||
* results, or start at a particular offset.
|
||||
*
|
||||
* @param string $query The query in string format
|
||||
* @param integer $limit The limit for the result set
|
||||
* @param integer $offset The offset for the result set
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function processLimit($query, $limit, $offset = 0)
|
||||
{
|
||||
if ($limit > 0 && $offset > 0) {
|
||||
$query .= ' LIMIT ' . $offset . ', ' . $limit;
|
||||
} elseif ($limit > 0) {
|
||||
$query .= ' LIMIT ' . $limit;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates an array of column names or values.
|
||||
*
|
||||
* @param string[] $values An array of values to concatenate.
|
||||
* @param string|null $separator As separator to place between each value.
|
||||
*
|
||||
* @return string The concatenated values.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function concatenate($values, $separator = null)
|
||||
{
|
||||
if ($separator !== null) {
|
||||
$statement = 'CONCAT_WS(' . $this->quote($separator);
|
||||
|
||||
foreach ($values as $value) {
|
||||
$statement .= ', ' . $value;
|
||||
}
|
||||
|
||||
return $statement . ')';
|
||||
}
|
||||
|
||||
return 'CONCAT(' . implode(',', $values) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate function to get input values concatenated into a string, separated by delimiter
|
||||
*
|
||||
* Usage:
|
||||
* $query->groupConcat('id', ',');
|
||||
*
|
||||
* @param string $expression The expression to apply concatenation to, this may be a column name or complex SQL statement.
|
||||
* @param string $separator The delimiter of each concatenated value
|
||||
*
|
||||
* @return string Input values concatenated into a string, separated by delimiter
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function groupConcat($expression, $separator = ',')
|
||||
{
|
||||
return 'GROUP_CONCAT(' . $expression . ' SEPARATOR ' . $this->quote($separator) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to quote and optionally escape a string to database requirements for insertion into the database.
|
||||
*
|
||||
* This method is provided for use where the query object is passed to a function for modification.
|
||||
* If you have direct access to the database object, it is recommended you use the quote method directly.
|
||||
*
|
||||
* Note that 'q' is an alias for this method as it is in DatabaseDriver.
|
||||
*
|
||||
* Usage:
|
||||
* $query->quote('fulltext');
|
||||
* $query->q('fulltext');
|
||||
* $query->q(array('option', 'fulltext'));
|
||||
*
|
||||
* @param array|string $text A string or an array of strings to quote.
|
||||
* @param boolean $escape True (default) to escape the string, false to leave it unchanged.
|
||||
*
|
||||
* @return string The quoted input string.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException if the internal db property is not a valid object.
|
||||
*/
|
||||
abstract public function quote($text, $escape = true);
|
||||
|
||||
/**
|
||||
* Get the regular expression operator
|
||||
*
|
||||
* Usage:
|
||||
* $query->where('field ' . $query->regexp($search));
|
||||
*
|
||||
* @param string $value The regex pattern.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function regexp($value)
|
||||
{
|
||||
return ' REGEXP ' . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the function to return a random floating-point value
|
||||
*
|
||||
* Usage:
|
||||
* $query->rand();
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function rand()
|
||||
{
|
||||
return ' RAND() ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a value in a varchar used like a set.
|
||||
*
|
||||
* Ensure that the value is an integer before passing to the method.
|
||||
*
|
||||
* Usage:
|
||||
* $query->findInSet((int) $parent->id, 'a.assigned_cat_ids')
|
||||
*
|
||||
* @param string $value The value to search for.
|
||||
* @param string $set The set of values.
|
||||
*
|
||||
* @return string A representation of the MySQL find_in_set() function for the driver.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function findInSet($value, $set)
|
||||
{
|
||||
return ' find_in_set(' . $value . ', ' . $set . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of the current row.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select('id');
|
||||
* $query->selectRowNumber('ordering,publish_up DESC', 'new_ordering');
|
||||
* $query->from('#__content');
|
||||
*
|
||||
* @param string $orderBy An expression of ordering for window function.
|
||||
* @param string $orderColumnAlias An alias for new ordering column.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function selectRowNumber($orderBy, $orderColumnAlias)
|
||||
{
|
||||
$this->validateRowNumber($orderBy, $orderColumnAlias);
|
||||
|
||||
return $this->select("(SELECT @rownum := @rownum + 1 FROM (SELECT @rownum := 0) AS r) AS $orderColumnAlias");
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts a value to a char.
|
||||
*
|
||||
* Ensure that the value is properly quoted before passing to the method.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->castAs('CHAR', 'a'));
|
||||
*
|
||||
* @param string $type The type of string to cast as.
|
||||
* @param string $value The value to cast as a char.
|
||||
* @param string $length The value to cast as a char.
|
||||
*
|
||||
* @return string SQL statement to cast the value as a char type.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function castAs(string $type, string $value, ?string $length = null)
|
||||
{
|
||||
switch (strtoupper($type)) {
|
||||
case 'CHAR':
|
||||
if (!$length) {
|
||||
return $value;
|
||||
} else {
|
||||
return 'CAST(' . $value . ' AS CHAR(' . $length . '))';
|
||||
}
|
||||
|
||||
// No break
|
||||
case 'INT':
|
||||
return '(' . $value . ' + 0)';
|
||||
}
|
||||
|
||||
return parent::castAs($type, $value, $length);
|
||||
}
|
||||
}
|
||||
696
libraries/vendor/joomla/database/src/Query/PostgresqlQueryBuilder.php
vendored
Normal file
696
libraries/vendor/joomla/database/src/Query/PostgresqlQueryBuilder.php
vendored
Normal file
@ -0,0 +1,696 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Query;
|
||||
|
||||
/**
|
||||
* Trait for PostgreSQL Query Building.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
trait PostgresqlQueryBuilder
|
||||
{
|
||||
/**
|
||||
* The FOR UPDATE element used in "FOR UPDATE" lock
|
||||
*
|
||||
* @var QueryElement
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $forUpdate;
|
||||
|
||||
/**
|
||||
* The FOR SHARE element used in "FOR SHARE" lock
|
||||
*
|
||||
* @var QueryElement
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $forShare;
|
||||
|
||||
/**
|
||||
* The NOWAIT element used in "FOR SHARE" and "FOR UPDATE" lock
|
||||
*
|
||||
* @var QueryElement
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $noWait;
|
||||
|
||||
/**
|
||||
* The LIMIT element
|
||||
*
|
||||
* @var QueryElement
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $limit;
|
||||
|
||||
/**
|
||||
* The OFFSET element
|
||||
*
|
||||
* @var QueryElement
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $offset;
|
||||
|
||||
/**
|
||||
* The RETURNING element of INSERT INTO
|
||||
*
|
||||
* @var QueryElement
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $returning;
|
||||
|
||||
/**
|
||||
* Magic function to convert the query to a string, only for PostgreSQL specific queries
|
||||
*
|
||||
* @return string The completed query.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$query = '';
|
||||
|
||||
switch ($this->type) {
|
||||
case 'select':
|
||||
$query .= (string) $this->select;
|
||||
$query .= (string) $this->from;
|
||||
|
||||
if ($this->join) {
|
||||
// Special case for joins
|
||||
foreach ($this->join as $join) {
|
||||
$query .= (string) $join;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->where) {
|
||||
$query .= (string) $this->where;
|
||||
}
|
||||
|
||||
if ($this->selectRowNumber) {
|
||||
if ($this->order) {
|
||||
$query .= (string) $this->order;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->group) {
|
||||
$query .= (string) $this->group;
|
||||
}
|
||||
|
||||
if ($this->having) {
|
||||
$query .= (string) $this->having;
|
||||
}
|
||||
|
||||
if ($this->merge) {
|
||||
// Special case for merge
|
||||
foreach ($this->merge as $element) {
|
||||
$query .= (string) $element;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->order) {
|
||||
$query .= (string) $this->order;
|
||||
}
|
||||
|
||||
if ($this->forUpdate) {
|
||||
$query .= (string) $this->forUpdate;
|
||||
} else {
|
||||
if ($this->forShare) {
|
||||
$query .= (string) $this->forShare;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->noWait) {
|
||||
$query .= (string) $this->noWait;
|
||||
}
|
||||
|
||||
$query = $this->processLimit($query, $this->limit, $this->offset);
|
||||
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
$query .= (string) $this->update;
|
||||
$query .= (string) $this->set;
|
||||
|
||||
if ($this->join) {
|
||||
$tmpFrom = $this->from;
|
||||
$tmpWhere = $this->where ? clone $this->where : null;
|
||||
$this->from = null;
|
||||
|
||||
// Workaround for special case of JOIN with UPDATE
|
||||
foreach ($this->join as $join) {
|
||||
$joinElem = $join->getElements();
|
||||
|
||||
$this->from($joinElem[0]);
|
||||
|
||||
if (isset($joinElem[1])) {
|
||||
$this->where($joinElem[1]);
|
||||
}
|
||||
}
|
||||
|
||||
$query .= (string) $this->from;
|
||||
|
||||
if ($this->where) {
|
||||
$query .= (string) $this->where;
|
||||
}
|
||||
|
||||
$this->from = $tmpFrom;
|
||||
$this->where = $tmpWhere;
|
||||
} elseif ($this->where) {
|
||||
$query .= (string) $this->where;
|
||||
}
|
||||
|
||||
$query = $this->processLimit($query, $this->limit, $this->offset);
|
||||
|
||||
break;
|
||||
|
||||
case 'insert':
|
||||
$query .= (string) $this->insert;
|
||||
|
||||
if ($this->values) {
|
||||
if ($this->columns) {
|
||||
$query .= (string) $this->columns;
|
||||
}
|
||||
|
||||
$elements = $this->values->getElements();
|
||||
|
||||
if (!($elements[0] instanceof $this)) {
|
||||
$query .= ' VALUES ';
|
||||
}
|
||||
|
||||
$query .= (string) $this->values;
|
||||
|
||||
if ($this->returning) {
|
||||
$query .= (string) $this->returning;
|
||||
}
|
||||
}
|
||||
|
||||
$query = $this->processLimit($query, $this->limit, $this->offset);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$query = parent::__toString();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->type === 'select' && $this->alias !== null) {
|
||||
$query = '(' . $query . ') AS ' . $this->alias;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear data from the query or a specific clause of the query.
|
||||
*
|
||||
* @param string $clause Optionally, the name of the clause to clear, or nothing to clear the whole query.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function clear($clause = null)
|
||||
{
|
||||
switch ($clause) {
|
||||
case 'limit':
|
||||
$this->limit = null;
|
||||
|
||||
break;
|
||||
|
||||
case 'offset':
|
||||
$this->offset = null;
|
||||
|
||||
break;
|
||||
|
||||
case 'forUpdate':
|
||||
$this->forUpdate = null;
|
||||
|
||||
break;
|
||||
|
||||
case 'forShare':
|
||||
$this->forShare = null;
|
||||
|
||||
break;
|
||||
|
||||
case 'noWait':
|
||||
$this->noWait = null;
|
||||
|
||||
break;
|
||||
|
||||
case 'returning':
|
||||
$this->returning = null;
|
||||
|
||||
break;
|
||||
|
||||
case 'select':
|
||||
case 'update':
|
||||
case 'delete':
|
||||
case 'insert':
|
||||
case 'querySet':
|
||||
case 'from':
|
||||
case 'join':
|
||||
case 'set':
|
||||
case 'where':
|
||||
case 'group':
|
||||
case 'having':
|
||||
case 'merge':
|
||||
case 'order':
|
||||
case 'columns':
|
||||
case 'values':
|
||||
parent::clear($clause);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->forUpdate = null;
|
||||
$this->forShare = null;
|
||||
$this->noWait = null;
|
||||
$this->returning = null;
|
||||
|
||||
parent::clear($clause);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts a value to a char.
|
||||
*
|
||||
* Ensure that the value is properly quoted before passing to the method.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->castAs('CHAR', 'a'));
|
||||
*
|
||||
* @param string $type The type of string to cast as.
|
||||
* @param string $value The value to cast as a char.
|
||||
* @param ?string $length The value to cast as a char.
|
||||
*
|
||||
* @return string SQL statement to cast the value as a char type.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function castAs(string $type, string $value, ?string $length = null)
|
||||
{
|
||||
switch (strtoupper($type)) {
|
||||
case 'CHAR':
|
||||
if (!$length) {
|
||||
return $value . '::text';
|
||||
} else {
|
||||
return 'CAST(' . $value . ' AS CHAR(' . $length . '))';
|
||||
}
|
||||
|
||||
// No break
|
||||
case 'INT':
|
||||
return 'CAST(' . $value . ' AS INTEGER)';
|
||||
}
|
||||
|
||||
return parent::castAs($type, $value, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates an array of column names or values.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->concatenate(array('a', 'b')));
|
||||
*
|
||||
* @param string[] $values An array of values to concatenate.
|
||||
* @param string|null $separator As separator to place between each value.
|
||||
*
|
||||
* @return string The concatenated values.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function concatenate($values, $separator = null)
|
||||
{
|
||||
if ($separator !== null) {
|
||||
return implode(' || ' . $this->quote($separator) . ' || ', $values);
|
||||
}
|
||||
|
||||
return implode(' || ', $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current date and time.
|
||||
*
|
||||
* @return string Return string used in query to obtain
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function currentTimestamp()
|
||||
{
|
||||
return 'NOW()';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the FOR UPDATE lock on select's output row
|
||||
*
|
||||
* @param string $tableName The table to lock
|
||||
* @param string $glue The glue by which to join the conditions. Defaults to ',' .
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function forUpdate($tableName, $glue = ',')
|
||||
{
|
||||
$this->type = 'forUpdate';
|
||||
|
||||
if ($this->forUpdate === null) {
|
||||
$glue = strtoupper($glue);
|
||||
$this->forUpdate = new QueryElement('FOR UPDATE', 'OF ' . $tableName, "$glue ");
|
||||
} else {
|
||||
$this->forUpdate->append($tableName);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the FOR SHARE lock on select's output row
|
||||
*
|
||||
* @param string $tableName The table to lock
|
||||
* @param string $glue The glue by which to join the conditions. Defaults to ',' .
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function forShare($tableName, $glue = ',')
|
||||
{
|
||||
$this->type = 'forShare';
|
||||
|
||||
if ($this->forShare === null) {
|
||||
$glue = strtoupper($glue);
|
||||
$this->forShare = new QueryElement('FOR SHARE', 'OF ' . $tableName, "$glue ");
|
||||
} else {
|
||||
$this->forShare->append($tableName);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate function to get input values concatenated into a string, separated by delimiter
|
||||
*
|
||||
* Usage:
|
||||
* $query->groupConcat('id', ',');
|
||||
*
|
||||
* @param string $expression The expression to apply concatenation to, this may be a column name or complex SQL statement.
|
||||
* @param string $separator The delimiter of each concatenated value
|
||||
*
|
||||
* @return string Input values concatenated into a string, separated by delimiter
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function groupConcat($expression, $separator = ',')
|
||||
{
|
||||
return 'string_agg(' . $expression . ', ' . $this->quote($separator) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a string to extract year from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->year($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing year to be extracted.
|
||||
*
|
||||
* @return string Returns string to extract year from a date.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function year($date)
|
||||
{
|
||||
return 'EXTRACT (YEAR FROM ' . $date . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a string to extract month from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->month($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing month to be extracted.
|
||||
*
|
||||
* @return string Returns string to extract month from a date.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function month($date)
|
||||
{
|
||||
return 'EXTRACT (MONTH FROM ' . $date . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a string to extract day from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->day($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing day to be extracted.
|
||||
*
|
||||
* @return string Returns string to extract day from a date.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function day($date)
|
||||
{
|
||||
return 'EXTRACT (DAY FROM ' . $date . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a string to extract hour from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->hour($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing hour to be extracted.
|
||||
*
|
||||
* @return string Returns string to extract hour from a date.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function hour($date)
|
||||
{
|
||||
return 'EXTRACT (HOUR FROM ' . $date . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a string to extract minute from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->minute($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing minute to be extracted.
|
||||
*
|
||||
* @return string Returns string to extract minute from a date.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function minute($date)
|
||||
{
|
||||
return 'EXTRACT (MINUTE FROM ' . $date . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a string to extract seconds from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->second($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing second to be extracted.
|
||||
*
|
||||
* @return string Returns string to extract second from a date.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function second($date)
|
||||
{
|
||||
return 'EXTRACT (SECOND FROM ' . $date . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the NOWAIT lock on select's output row
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function noWait()
|
||||
{
|
||||
$this->type = 'noWait';
|
||||
|
||||
if ($this->noWait === null) {
|
||||
$this->noWait = new QueryElement('NOWAIT', null);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the LIMIT clause to the query
|
||||
*
|
||||
* @param integer $limit Number of rows to return
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function limit($limit = 0)
|
||||
{
|
||||
if ($this->limit === null) {
|
||||
$this->limit = new QueryElement('LIMIT', (int) $limit);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the OFFSET clause to the query
|
||||
*
|
||||
* @param integer $offset An integer for skipping rows
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function offset($offset = 0)
|
||||
{
|
||||
if ($this->offset === null) {
|
||||
$this->offset = new QueryElement('OFFSET', (int) $offset);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the RETURNING element to INSERT INTO statement.
|
||||
*
|
||||
* @param mixed $pkCol The name of the primary key column.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function returning($pkCol)
|
||||
{
|
||||
if ($this->returning === null) {
|
||||
$this->returning = new QueryElement('RETURNING', $pkCol);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to modify a query already in string format with the needed additions to make the query limited to a particular number of
|
||||
* results, or start at a particular offset.
|
||||
*
|
||||
* @param string $query The query in string format
|
||||
* @param integer $limit The limit for the result set
|
||||
* @param integer $offset The offset for the result set
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function processLimit($query, $limit, $offset = 0)
|
||||
{
|
||||
if ($limit > 0) {
|
||||
$query .= ' LIMIT ' . $limit;
|
||||
}
|
||||
|
||||
if ($offset > 0) {
|
||||
$query .= ' OFFSET ' . $offset;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to the current date and time.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->dateAdd());
|
||||
*
|
||||
* Prefixing the interval with a - (negative sign) will cause subtraction to be used.
|
||||
*
|
||||
* @param string $date The db quoted string representation of the date to add to
|
||||
* @param string $interval The string representation of the appropriate number of units
|
||||
* @param string $datePart The part of the date to perform the addition on
|
||||
*
|
||||
* @return string The string with the appropriate sql for addition of dates
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @link http://www.postgresql.org/docs/9.0/static/functions-datetime.html.
|
||||
*/
|
||||
public function dateAdd($date, $interval, $datePart)
|
||||
{
|
||||
if (substr($interval, 0, 1) !== '-') {
|
||||
return 'timestamp ' . $date . " + interval '" . $interval . ' ' . $datePart . "'";
|
||||
}
|
||||
|
||||
return 'timestamp ' . $date . " - interval '" . ltrim($interval, '-') . ' ' . $datePart . "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the regular expression operator
|
||||
*
|
||||
* Usage:
|
||||
* $query->where('field ' . $query->regexp($search));
|
||||
*
|
||||
* @param string $value The regex pattern.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function regexp($value)
|
||||
{
|
||||
return ' ~* ' . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the function to return a random floating-point value
|
||||
*
|
||||
* Usage:
|
||||
* $query->rand();
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function rand()
|
||||
{
|
||||
return ' RANDOM() ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a value in a varchar used like a set.
|
||||
*
|
||||
* Ensure that the value is an integer before passing to the method.
|
||||
*
|
||||
* Usage:
|
||||
* $query->findInSet((int) $parent->id, 'a.assigned_cat_ids')
|
||||
*
|
||||
* @param string $value The value to search for.
|
||||
* @param string $set The set of values.
|
||||
*
|
||||
* @return string A representation of the MySQL find_in_set() function for the driver.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function findInSet($value, $set)
|
||||
{
|
||||
return " $value = ANY (string_to_array($set, ',')::integer[]) ";
|
||||
}
|
||||
}
|
||||
75
libraries/vendor/joomla/database/src/Query/PreparableInterface.php
vendored
Normal file
75
libraries/vendor/joomla/database/src/Query/PreparableInterface.php
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Query;
|
||||
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
trigger_deprecation(
|
||||
'joomla/database',
|
||||
'2.0.0',
|
||||
'%s() is deprecated and will be removed in 3.0, all query objects should implement %s instead.',
|
||||
PreparableInterface::class,
|
||||
QueryInterface::class
|
||||
);
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Joomla Database Query Preparable Interface.
|
||||
*
|
||||
* Adds bind/unbind methods as well as a getBounded() method to retrieve the stored bounded variables on demand prior to query execution.
|
||||
*
|
||||
* @since 1.0
|
||||
* @deprecated 3.0 Capabilities will be required in Joomla\Database\QueryInterface
|
||||
*/
|
||||
interface PreparableInterface
|
||||
{
|
||||
/**
|
||||
* Method to add a variable to an internal array that will be bound to a prepared SQL statement before query execution.
|
||||
*
|
||||
* @param array|string|integer $key The key that will be used in your SQL query to reference the value. Usually of
|
||||
* the form ':key', but can also be an integer.
|
||||
* @param mixed $value The value that will be bound. It can be an array, in this case it has to be
|
||||
* same length of $key; The value is passed by reference to support output
|
||||
* parameters such as those possible with stored procedures.
|
||||
* @param array|string $dataType Constant corresponding to a SQL datatype. It can be an array, in this case it
|
||||
* has to be same length of $key
|
||||
* @param integer $length The length of the variable. Usually required for OUTPUT parameters.
|
||||
* @param array $driverOptions Optional driver options to be used.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function bind($key, &$value, $dataType = ParameterType::STRING, $length = 0, $driverOptions = []);
|
||||
|
||||
/**
|
||||
* Method to unbind a bound variable.
|
||||
*
|
||||
* @param array|string|integer $key The key or array of keys to unbind.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function unbind($key);
|
||||
|
||||
/**
|
||||
* Retrieves the bound parameters array when key is null and returns it by reference. If a key is provided then that item is returned.
|
||||
*
|
||||
* @param mixed $key The bounded variable key to retrieve.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function &getBounded($key = null);
|
||||
}
|
||||
170
libraries/vendor/joomla/database/src/Query/QueryElement.php
vendored
Normal file
170
libraries/vendor/joomla/database/src/Query/QueryElement.php
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Query;
|
||||
|
||||
/**
|
||||
* Query Element Class.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class QueryElement
|
||||
{
|
||||
/**
|
||||
* The name of the element.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* An array of elements.
|
||||
*
|
||||
* @var string[]
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $elements = [];
|
||||
|
||||
/**
|
||||
* Glue piece.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $glue;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
* @param string[]|string $elements String or array.
|
||||
* @param string $glue The glue for elements.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __construct($name, $elements, $glue = ',')
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->glue = $glue;
|
||||
|
||||
$this->append($elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic function to convert the query element to a string.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
if (substr($this->name, -2) === '()') {
|
||||
return \PHP_EOL . substr($this->name, 0, -2) . '(' . implode($this->glue, $this->elements) . ')';
|
||||
}
|
||||
|
||||
return \PHP_EOL . $this->name . ' ' . implode($this->glue, $this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends element parts to the internal list.
|
||||
*
|
||||
* @param string[]|string $elements String or array.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function append($elements)
|
||||
{
|
||||
if (\is_array($elements)) {
|
||||
$this->elements = array_merge($this->elements, $elements);
|
||||
} else {
|
||||
$this->elements = array_merge($this->elements, [$elements]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the elements of this element.
|
||||
*
|
||||
* @return string[]
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getElements()
|
||||
{
|
||||
return $this->elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the glue of this element.
|
||||
*
|
||||
* @return string Glue of the element.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function getGlue()
|
||||
{
|
||||
return $this->glue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this element.
|
||||
*
|
||||
* @return string Name of the element.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of this element.
|
||||
*
|
||||
* @param string $name Name of the element.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to provide basic copy support.
|
||||
*
|
||||
* Any object pushed into the data of this class should have its own __clone() implementation.
|
||||
* This method does not support copying objects in a multidimensional array.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
foreach ($this as $k => $v) {
|
||||
if (\is_object($v)) {
|
||||
$this->{$k} = clone $v;
|
||||
} elseif (\is_array($v)) {
|
||||
foreach ($v as $i => $element) {
|
||||
if (\is_object($element)) {
|
||||
$this->{$k}[$i] = clone $element;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
725
libraries/vendor/joomla/database/src/QueryInterface.php
vendored
Normal file
725
libraries/vendor/joomla/database/src/QueryInterface.php
vendored
Normal file
@ -0,0 +1,725 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
use Joomla\Database\Exception\QueryTypeAlreadyDefinedException;
|
||||
use Joomla\Database\Query\LimitableInterface;
|
||||
use Joomla\Database\Query\PreparableInterface;
|
||||
use Joomla\Database\Exception\UnknownTypeException;
|
||||
|
||||
/**
|
||||
* Joomla Framework Query Building Interface.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface QueryInterface extends PreparableInterface, LimitableInterface
|
||||
{
|
||||
/**
|
||||
* Convert the query object to a string.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __toString();
|
||||
|
||||
/**
|
||||
* Add a single column, or array of columns to the CALL clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->call('a.*')->call('b.id');
|
||||
* $query->call(array('a.*', 'b.id'));
|
||||
*
|
||||
* @param array|string $columns A string or an array of field names.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws QueryTypeAlreadyDefinedException if the query type has already been defined
|
||||
*/
|
||||
public function call($columns);
|
||||
|
||||
/**
|
||||
* Casts a value to a specified type.
|
||||
*
|
||||
* Ensure that the value is properly quoted before passing to the method.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->castAs('CHAR', 'a'));
|
||||
*
|
||||
* @param string $type The type of string to cast as.
|
||||
* @param string $value The value to cast as a char.
|
||||
* @param string $length Optionally specify the length of the field (if the type supports it otherwise
|
||||
* ignored).
|
||||
*
|
||||
* @return string SQL statement to cast the value as a char type.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws UnknownTypeException When unsupported cast for a database driver
|
||||
*/
|
||||
public function castAs(string $type, string $value, ?string $length = null);
|
||||
|
||||
/**
|
||||
* Gets the number of characters in a string.
|
||||
*
|
||||
* Note, use 'length' to find the number of bytes in a string.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->charLength('a'));
|
||||
*
|
||||
* @param string $field A value.
|
||||
* @param string|null $operator Comparison operator between charLength integer value and $condition
|
||||
* @param string|null $condition Integer value to compare charLength with.
|
||||
*
|
||||
* @return string SQL statement to get the length of a character.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function charLength($field, $operator = null, $condition = null);
|
||||
|
||||
/**
|
||||
* Clear data from the query or a specific clause of the query.
|
||||
*
|
||||
* @param string $clause Optionally, the name of the clause to clear, or nothing to clear the whole query.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function clear($clause = null);
|
||||
|
||||
/**
|
||||
* Adds a column, or array of column names that would be used for an INSERT INTO statement.
|
||||
*
|
||||
* @param array|string $columns A column name, or array of column names.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function columns($columns);
|
||||
|
||||
/**
|
||||
* Concatenates an array of column names or values.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->concatenate(array('a', 'b')));
|
||||
*
|
||||
* @param string[] $values An array of values to concatenate.
|
||||
* @param string|null $separator As separator to place between each value.
|
||||
*
|
||||
* @return string SQL statement representing the concatenated values.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function concatenate($values, $separator = null);
|
||||
|
||||
/**
|
||||
* Gets the current date and time.
|
||||
*
|
||||
* Usage:
|
||||
* $query->where('published_up < '.$query->currentTimestamp());
|
||||
*
|
||||
* @return string SQL statement to get the current timestamp.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function currentTimestamp();
|
||||
|
||||
/**
|
||||
* Add a table name to the DELETE clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->delete('#__a')->where('id = 1');
|
||||
*
|
||||
* @param string $table The name of the table to delete from.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws QueryTypeAlreadyDefinedException if the query type has already been defined
|
||||
*/
|
||||
public function delete($table = null);
|
||||
|
||||
/**
|
||||
* Add a single column, or array of columns to the EXEC clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->exec('a.*')->exec('b.id');
|
||||
* $query->exec(array('a.*', 'b.id'));
|
||||
*
|
||||
* @param array|string $columns A string or an array of field names.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws QueryTypeAlreadyDefinedException if the query type has already been defined
|
||||
*/
|
||||
public function exec($columns);
|
||||
|
||||
/**
|
||||
* Find a value in a varchar used like a set.
|
||||
*
|
||||
* Ensure that the value is an integer before passing to the method.
|
||||
*
|
||||
* Usage:
|
||||
* $query->findInSet((int) $parent->id, 'a.assigned_cat_ids')
|
||||
*
|
||||
* @param string $value The value to search for.
|
||||
* @param string $set The set of values.
|
||||
*
|
||||
* @return string A representation of the MySQL find_in_set() function for the driver.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function findInSet($value, $set);
|
||||
|
||||
/**
|
||||
* Add a table to the FROM clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select('*')->from('#__a');
|
||||
* $query->select('*')->from($subquery->alias('a'));
|
||||
*
|
||||
* @param string|QueryInterface $table The name of the table or a QueryInterface object (or a child of it) with alias set.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function from($table);
|
||||
|
||||
/**
|
||||
* Add alias for current query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select('*')->from('#__a')->alias('subquery');
|
||||
*
|
||||
* @param string $alias Alias used for a JDatabaseQuery.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function alias($alias);
|
||||
|
||||
/**
|
||||
* Used to get a string to extract year from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->year($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing year to be extracted.
|
||||
*
|
||||
* @return string SQL statement to get the year from a date value.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function year($date);
|
||||
|
||||
/**
|
||||
* Used to get a string to extract month from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->month($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing month to be extracted.
|
||||
*
|
||||
* @return string SQL statement to get the month from a date value.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function month($date);
|
||||
|
||||
/**
|
||||
* Used to get a string to extract day from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->day($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing day to be extracted.
|
||||
*
|
||||
* @return string SQL statement to get the day from a date value.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function day($date);
|
||||
|
||||
/**
|
||||
* Used to get a string to extract hour from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->hour($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing hour to be extracted.
|
||||
*
|
||||
* @return string SQL statement to get the hour from a date/time value.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function hour($date);
|
||||
|
||||
/**
|
||||
* Used to get a string to extract minute from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->minute($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing minute to be extracted.
|
||||
*
|
||||
* @return string SQL statement to get the minute from a date/time value.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function minute($date);
|
||||
|
||||
/**
|
||||
* Used to get a string to extract seconds from date column.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->second($query->quoteName('dateColumn')));
|
||||
*
|
||||
* @param string $date Date column containing second to be extracted.
|
||||
*
|
||||
* @return string SQL statement to get the second from a date/time value.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function second($date);
|
||||
|
||||
/**
|
||||
* Add a grouping column to the GROUP clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->group('id');
|
||||
*
|
||||
* @param array|string $columns A string or array of ordering columns.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function group($columns);
|
||||
|
||||
/**
|
||||
* Aggregate function to get input values concatenated into a string, separated by delimiter
|
||||
*
|
||||
* Usage:
|
||||
* $query->groupConcat('id', ',');
|
||||
*
|
||||
* @param string $expression The expression to apply concatenation to, this may be a column name or complex SQL statement.
|
||||
* @param string $separator The delimiter of each concatenated value
|
||||
*
|
||||
* @return string Input values concatenated into a string, separated by delimiter
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function groupConcat($expression, $separator = ',');
|
||||
|
||||
/**
|
||||
* A conditions to the HAVING clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->group('id')->having('COUNT(id) > 5');
|
||||
*
|
||||
* @param array|string $conditions A string or array of columns.
|
||||
* @param string $glue The glue by which to join the conditions. Defaults to AND.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function having($conditions, $glue = 'AND');
|
||||
|
||||
/**
|
||||
* Add a table name to the INSERT clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->insert('#__a')->set('id = 1');
|
||||
* $query->insert('#__a')->columns('id, title')->values('1,2')->values('3,4');
|
||||
* $query->insert('#__a')->columns('id, title')->values(array('1,2', '3,4'));
|
||||
*
|
||||
* @param string $table The name of the table to insert data into.
|
||||
* @param boolean $incrementField The name of the field to auto increment.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws QueryTypeAlreadyDefinedException if the query type has already been defined
|
||||
*/
|
||||
public function insert($table, $incrementField = false);
|
||||
|
||||
/**
|
||||
* Add a JOIN clause to the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->join('INNER', 'b', 'b.id = a.id);
|
||||
*
|
||||
* @param string $type The type of join. This string is prepended to the JOIN keyword.
|
||||
* @param string $table The name of table.
|
||||
* @param string $condition The join condition.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function join($type, $table, $condition = null);
|
||||
|
||||
/**
|
||||
* Get the length of a string in bytes.
|
||||
*
|
||||
* Note, use 'charLength' to find the number of characters in a string.
|
||||
*
|
||||
* Usage:
|
||||
* query->where($query->length('a').' > 3');
|
||||
*
|
||||
* @param string $value The string to measure.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function length($value);
|
||||
|
||||
/**
|
||||
* Get the null or zero representation of a timestamp for the database driver.
|
||||
*
|
||||
* This method is provided for use where the query object is passed to a function for modification.
|
||||
* If you have direct access to the database object, it is recommended you use the nullDate method directly.
|
||||
*
|
||||
* Usage:
|
||||
* $query->where('modified_date <> '.$query->nullDate());
|
||||
*
|
||||
* @param boolean $quoted Optionally wraps the null date in database quotes (true by default).
|
||||
*
|
||||
* @return string Null or zero representation of a timestamp.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function nullDate($quoted = true);
|
||||
|
||||
/**
|
||||
* Generate a SQL statement to check if column represents a zero or null datetime.
|
||||
*
|
||||
* Usage:
|
||||
* $query->where($query->isNullDatetime('modified_date'));
|
||||
*
|
||||
* @param string $column A column name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function isNullDatetime($column);
|
||||
|
||||
/**
|
||||
* Add an ordering column to the ORDER clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->order('foo')->order('bar');
|
||||
* $query->order(array('foo','bar'));
|
||||
*
|
||||
* @param array|string $columns A string or array of ordering columns.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function order($columns);
|
||||
|
||||
/**
|
||||
* Wrap an SQL statement identifier name such as column, table or database names in quotes to prevent injection
|
||||
* risks and reserved word conflicts.
|
||||
*
|
||||
* This method is provided for use where the query object is passed to a function for modification.
|
||||
* If you have direct access to the database object, it is recommended you use the quoteName method directly.
|
||||
*
|
||||
* Note that 'qn' is an alias for this method as it is in DatabaseDriver.
|
||||
*
|
||||
* Usage:
|
||||
* $query->quoteName('#__a');
|
||||
* $query->qn('#__a');
|
||||
*
|
||||
* @param array|string $name The identifier name to wrap in quotes, or an array of identifier names to wrap in quotes.
|
||||
* Each type supports dot-notation name.
|
||||
* @param array|string $as The AS query part associated to $name. It can be string or array, in latter case it has to be
|
||||
* same length of $name; if is null there will not be any AS part for string or array element.
|
||||
*
|
||||
* @return array|string The quote wrapped name, same type of $name.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException if the internal db property is not a valid object.
|
||||
*/
|
||||
public function quoteName($name, $as = null);
|
||||
|
||||
/**
|
||||
* Get the function to return a random floating-point value
|
||||
*
|
||||
* Usage:
|
||||
* $query->rand();
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function rand();
|
||||
|
||||
/**
|
||||
* Get the regular expression operator
|
||||
*
|
||||
* Usage:
|
||||
* $query->where('field ' . $query->regexp($search));
|
||||
*
|
||||
* @param string $value The regex pattern.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function regexp($value);
|
||||
|
||||
/**
|
||||
* Add a single column, or array of columns to the SELECT clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select('a.*')->select('b.id');
|
||||
* $query->select(array('a.*', 'b.id'));
|
||||
*
|
||||
* @param array|string $columns A string or an array of field names.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws QueryTypeAlreadyDefinedException if the query type has already been defined
|
||||
*/
|
||||
public function select($columns);
|
||||
|
||||
/**
|
||||
* Return the number of the current row.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select('id');
|
||||
* $query->selectRowNumber('ordering,publish_up DESC', 'new_ordering');
|
||||
* $query->from('#__content');
|
||||
*
|
||||
* @param string $orderBy An expression of ordering for window function.
|
||||
* @param string $orderColumnAlias An alias for new ordering column.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function selectRowNumber($orderBy, $orderColumnAlias);
|
||||
|
||||
/**
|
||||
* Add a single condition string, or an array of strings to the SET clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->set('a = 1')->set('b = 2');
|
||||
* $query->set(array('a = 1', 'b = 2');
|
||||
*
|
||||
* @param array|string $conditions A string or array of string conditions.
|
||||
* @param string $glue The glue by which to join the condition strings. Defaults to `,`.
|
||||
* Note that the glue is set on first use and cannot be changed.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function set($conditions, $glue = ',');
|
||||
|
||||
/**
|
||||
* Add a table name to the UPDATE clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->update('#__foo')->set(...);
|
||||
*
|
||||
* @param string $table A table to update.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws QueryTypeAlreadyDefinedException if the query type has already been defined
|
||||
*/
|
||||
public function update($table);
|
||||
|
||||
/**
|
||||
* Adds a tuple, or array of tuples that would be used as values for an INSERT INTO statement.
|
||||
*
|
||||
* Usage:
|
||||
* $query->values('1,2,3')->values('4,5,6');
|
||||
* $query->values(array('1,2,3', '4,5,6'));
|
||||
*
|
||||
* @param array|string $values A single tuple, or array of tuples.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function values($values);
|
||||
|
||||
/**
|
||||
* Add a single condition, or an array of conditions to the WHERE clause of the query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->where('a = 1')->where('b = 2');
|
||||
* $query->where(array('a = 1', 'b = 2'));
|
||||
*
|
||||
* @param array|string $conditions A string or array of where conditions.
|
||||
* @param string $glue The glue by which to join the conditions. Defaults to AND.
|
||||
* Note that the glue is set on first use and cannot be changed.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function where($conditions, $glue = 'AND');
|
||||
|
||||
/**
|
||||
* Add a WHERE IN statement to the query.
|
||||
*
|
||||
* Note that all values must be the same data type.
|
||||
*
|
||||
* Usage
|
||||
* $query->whereIn('id', [1, 2, 3]);
|
||||
*
|
||||
* @param string $keyName Key name for the where clause
|
||||
* @param array $keyValues Array of values to be matched
|
||||
* @param array|string $dataType Constant corresponding to a SQL datatype. It can be an array, in this case it
|
||||
* has to be same length of $keyValues
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function whereIn(string $keyName, array $keyValues, $dataType = ParameterType::INTEGER);
|
||||
|
||||
/**
|
||||
* Add a WHERE NOT IN statement to the query.
|
||||
*
|
||||
* Note that all values must be the same data type.
|
||||
*
|
||||
* Usage
|
||||
* $query->whereNotIn('id', [1, 2, 3]);
|
||||
*
|
||||
* @param string $keyName Key name for the where clause
|
||||
* @param array $keyValues Array of values to be matched
|
||||
* @param array|string $dataType Constant corresponding to a SQL datatype. It can be an array, in this case it
|
||||
* has to be same length of $keyValues
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function whereNotIn(string $keyName, array $keyValues, $dataType = ParameterType::INTEGER);
|
||||
|
||||
/**
|
||||
* Extend the WHERE clause with a single condition or an array of conditions, with a potentially different logical operator from the one in the
|
||||
* current WHERE clause.
|
||||
*
|
||||
* Usage:
|
||||
* $query->where(array('a = 1', 'b = 2'))->extendWhere('XOR', array('c = 3', 'd = 4'));
|
||||
* will produce: WHERE ((a = 1 AND b = 2) XOR (c = 3 AND d = 4)
|
||||
*
|
||||
* @param string $outerGlue The glue by which to join the conditions to the current WHERE conditions.
|
||||
* @param mixed $conditions A string or array of WHERE conditions.
|
||||
* @param string $innerGlue The glue by which to join the conditions. Defaults to AND.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function extendWhere($outerGlue, $conditions, $innerGlue = 'AND');
|
||||
|
||||
/**
|
||||
* Binds an array of values and returns an array of prepared parameter names.
|
||||
*
|
||||
* Note that all values must be the same data type.
|
||||
*
|
||||
* Usage:
|
||||
* $query->whereIn('column in (' . implode(',', $query->bindArray($keyValues, $dataType)) . ')');
|
||||
*
|
||||
* @param array $values Values to bind
|
||||
* @param array|string $dataType Constant corresponding to a SQL datatype. It can be an array, in this case it
|
||||
* has to be same length of $key
|
||||
*
|
||||
* @return array An array with parameter names
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function bindArray(array $values, $dataType = ParameterType::INTEGER);
|
||||
|
||||
/**
|
||||
* Add a query to UNION with the current query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->union('SELECT name FROM #__foo')
|
||||
* $query->union('SELECT name FROM #__foo', true)
|
||||
*
|
||||
* @param DatabaseQuery|string $query The DatabaseQuery object or string to union.
|
||||
* @param boolean $distinct True to only return distinct rows from the union.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function union($query, $distinct = true);
|
||||
|
||||
/**
|
||||
* Add a query to UNION ALL with the current query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->unionAll('SELECT name FROM #__foo')
|
||||
*
|
||||
* @param DatabaseQuery|string $query The DatabaseQuery object or string to union.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see union
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public function unionAll($query);
|
||||
|
||||
/**
|
||||
* Set a single query to the query set.
|
||||
* On this type of DatabaseQuery you can use union(), unionAll(), order() and setLimit()
|
||||
*
|
||||
* Usage:
|
||||
* $query->querySet($query2->select('name')->from('#__foo')->order('id DESC')->setLimit(1))
|
||||
* ->unionAll($query3->select('name')->from('#__foo')->order('id')->setLimit(1))
|
||||
* ->order('name')
|
||||
* ->setLimit(1)
|
||||
*
|
||||
* @param DatabaseQuery|string $query The DatabaseQuery object or string.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function querySet($query);
|
||||
|
||||
/**
|
||||
* Create a DatabaseQuery object of type querySet from current query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select('name')->from('#__foo')->order('id DESC')->setLimit(1)
|
||||
* ->toQuerySet()
|
||||
* ->unionAll($query2->select('name')->from('#__foo')->order('id')->setLimit(1))
|
||||
* ->order('name')
|
||||
* ->setLimit(1)
|
||||
*
|
||||
* @return DatabaseQuery A new object of the DatabaseQuery.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function toQuerySet();
|
||||
}
|
||||
40
libraries/vendor/joomla/database/src/QueryMonitorInterface.php
vendored
Normal file
40
libraries/vendor/joomla/database/src/QueryMonitorInterface.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Interface defining a query monitor.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface QueryMonitorInterface
|
||||
{
|
||||
/**
|
||||
* Act on a query being started.
|
||||
*
|
||||
* @param string $sql The SQL to be executed.
|
||||
* @param object[]|null $boundParams List of bound params, used with the query.
|
||||
* Each item is an object that holds: value, dataType
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function startQuery(string $sql, ?array $boundParams = null): void;
|
||||
|
||||
/**
|
||||
* Act on a query being stopped.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function stopQuery(): void;
|
||||
}
|
||||
55
libraries/vendor/joomla/database/src/Service/DatabaseProvider.php
vendored
Normal file
55
libraries/vendor/joomla/database/src/Service/DatabaseProvider.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Service;
|
||||
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\DatabaseFactory;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
|
||||
/**
|
||||
* Database service provider
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class DatabaseProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->alias(DatabaseInterface::class, DatabaseDriver::class)
|
||||
->share(
|
||||
DatabaseDriver::class,
|
||||
function (Container $container) {
|
||||
/** @var \Joomla\Registry\Registry $config */
|
||||
$config = $container->get('config');
|
||||
$options = (array) $config->get('database');
|
||||
|
||||
return $container->get(DatabaseFactory::class)->getDriver($options['driver'], $options);
|
||||
}
|
||||
);
|
||||
|
||||
$container->share(
|
||||
DatabaseFactory::class,
|
||||
function (Container $container) {
|
||||
return new DatabaseFactory();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
29
libraries/vendor/joomla/database/src/Sqlazure/SqlazureDriver.php
vendored
Normal file
29
libraries/vendor/joomla/database/src/Sqlazure/SqlazureDriver.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Sqlazure;
|
||||
|
||||
use Joomla\Database\Sqlsrv\SqlsrvDriver;
|
||||
|
||||
/**
|
||||
* SQL Azure Database Driver
|
||||
*
|
||||
* @link https://msdn.microsoft.com/en-us/library/ee336279.aspx
|
||||
* @since 1.0
|
||||
*/
|
||||
class SqlazureDriver extends SqlsrvDriver
|
||||
{
|
||||
/**
|
||||
* The name of the database driver.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public $name = 'sqlazure';
|
||||
}
|
||||
21
libraries/vendor/joomla/database/src/Sqlazure/SqlazureQuery.php
vendored
Normal file
21
libraries/vendor/joomla/database/src/Sqlazure/SqlazureQuery.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Sqlazure;
|
||||
|
||||
use Joomla\Database\Sqlsrv\SqlsrvQuery;
|
||||
|
||||
/**
|
||||
* SQL Azure Query Building Class.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class SqlazureQuery extends SqlsrvQuery
|
||||
{
|
||||
}
|
||||
528
libraries/vendor/joomla/database/src/Sqlite/SqliteDriver.php
vendored
Normal file
528
libraries/vendor/joomla/database/src/Sqlite/SqliteDriver.php
vendored
Normal file
@ -0,0 +1,528 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Sqlite;
|
||||
|
||||
use Joomla\Database\Pdo\PdoDriver;
|
||||
|
||||
/**
|
||||
* SQLite database driver supporting PDO based connections
|
||||
*
|
||||
* @link https://www.php.net/manual/en/ref.pdo-sqlite.php
|
||||
* @since 1.0
|
||||
*/
|
||||
class SqliteDriver extends PdoDriver
|
||||
{
|
||||
/**
|
||||
* The name of the database driver.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public $name = 'sqlite';
|
||||
|
||||
/**
|
||||
* The character(s) used to quote SQL statement names such as table names or field names, etc.
|
||||
*
|
||||
* If a single character string the same character is used for both sides of the quoted name, else the first character will be used for the
|
||||
* opening quote and the second for the closing quote.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $nameQuote = '`';
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter database's character set.
|
||||
*
|
||||
* @param string $dbName The database name that will be altered
|
||||
*
|
||||
* @return boolean|resource
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function alterDbCharacterSet($dbName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the database if needed.
|
||||
*
|
||||
* @return void Returns void if the database connected successfully.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
if ($this->connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent::connect();
|
||||
|
||||
$this->connection->sqliteCreateFunction(
|
||||
'ROW_NUMBER',
|
||||
function ($init = null) {
|
||||
static $rownum, $partition;
|
||||
|
||||
if ($init !== null) {
|
||||
$rownum = $init;
|
||||
$partition = null;
|
||||
|
||||
return $rownum;
|
||||
}
|
||||
|
||||
$args = \func_get_args();
|
||||
array_shift($args);
|
||||
|
||||
$partitionBy = $args ? implode(',', $args) : null;
|
||||
|
||||
if ($partitionBy === null || $partitionBy === $partition) {
|
||||
$rownum++;
|
||||
} else {
|
||||
$rownum = 1;
|
||||
$partition = $partitionBy;
|
||||
}
|
||||
|
||||
return $rownum;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new database using information from $options object.
|
||||
*
|
||||
* @param \stdClass $options Object used to pass user and database name to database driver. This object must have "db_name" and "db_user" set.
|
||||
* @param boolean $utf True if the database supports the UTF-8 character set.
|
||||
*
|
||||
* @return boolean|resource
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function createDatabase($options, $utf = true)
|
||||
{
|
||||
// SQLite doesn't have a query for this
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to escape a string for usage in an SQLite statement.
|
||||
*
|
||||
* Note: Using query objects with bound variables is preferable to the below.
|
||||
*
|
||||
* @param string $text The string to be escaped.
|
||||
* @param boolean $extra Unused optional parameter to provide extra escaping.
|
||||
*
|
||||
* @return string The escaped string.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function escape($text, $extra = false)
|
||||
{
|
||||
if (\is_int($text)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
if (\is_float($text)) {
|
||||
// Force the dot as a decimal point.
|
||||
return str_replace(',', '.', $text);
|
||||
}
|
||||
|
||||
return \SQLite3::escapeString($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database collation in use by sampling a text field of a table in the database.
|
||||
*
|
||||
* @return string|boolean The collation in use by the database or boolean false if not supported.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getCollation()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database connection collation in use by sampling a text field of a table in the database.
|
||||
*
|
||||
* @return string|boolean The collation in use by the database connection (string) or boolean false if not supported.
|
||||
*
|
||||
* @since 1.6.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getConnectionCollation()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database encryption details (cipher and protocol) in use.
|
||||
*
|
||||
* @return string The database encryption details.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getConnectionEncryption(): string
|
||||
{
|
||||
// TODO: Not fake this
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test if the database TLS connections encryption are supported.
|
||||
*
|
||||
* @return boolean Whether the database supports TLS connections encryption.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function isConnectionEncryptionSupported(): bool
|
||||
{
|
||||
// TODO: Not fake this
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the table CREATE statement that creates the given tables.
|
||||
*
|
||||
* Note: Doesn't appear to have support in SQLite
|
||||
*
|
||||
* @param mixed $tables A table name or a list of table names.
|
||||
*
|
||||
* @return array A list of the create SQL for the tables.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableCreate($tables)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Sanitize input to an array and iterate over the list.
|
||||
$tables = (array) $tables;
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves field information about a given table.
|
||||
*
|
||||
* @param string $table The name of the database table.
|
||||
* @param boolean $typeOnly True to only return field types.
|
||||
*
|
||||
* @return array An array of fields for the database table.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableColumns($table, $typeOnly = true)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$columns = [];
|
||||
|
||||
$fieldCasing = $this->getOption(\PDO::ATTR_CASE);
|
||||
|
||||
$this->setOption(\PDO::ATTR_CASE, \PDO::CASE_UPPER);
|
||||
|
||||
$table = strtoupper($table);
|
||||
|
||||
$fields = $this->setQuery('pragma table_info(' . $table . ')')->loadObjectList();
|
||||
|
||||
if ($typeOnly) {
|
||||
foreach ($fields as $field) {
|
||||
$columns[$field->NAME] = $field->TYPE;
|
||||
}
|
||||
} else {
|
||||
foreach ($fields as $field) {
|
||||
// Do some dirty translation to MySQL output.
|
||||
// TODO: Come up with and implement a standard across databases.
|
||||
$columns[$field->NAME] = (object) [
|
||||
'Field' => $field->NAME,
|
||||
'Type' => $field->TYPE,
|
||||
'Null' => $field->NOTNULL == '1' ? 'NO' : 'YES',
|
||||
'Default' => $field->DFLT_VALUE,
|
||||
'Key' => $field->PK != '0' ? 'PRI' : '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$this->setOption(\PDO::ATTR_CASE, $fieldCasing);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of keys for a table.
|
||||
*
|
||||
* @param string $table The name of the table.
|
||||
*
|
||||
* @return array An array of the column specification for the table.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableKeys($table)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$keys = [];
|
||||
|
||||
$fieldCasing = $this->getOption(\PDO::ATTR_CASE);
|
||||
|
||||
$this->setOption(\PDO::ATTR_CASE, \PDO::CASE_UPPER);
|
||||
|
||||
$table = strtoupper($table);
|
||||
|
||||
$rows = $this->setQuery('pragma table_info( ' . $table . ')')->loadObjectList();
|
||||
|
||||
foreach ($rows as $column) {
|
||||
if ($column->PK == 1) {
|
||||
$keys[$column->NAME] = $column;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setOption(\PDO::ATTR_CASE, $fieldCasing);
|
||||
|
||||
return $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of all tables in the database (schema).
|
||||
*
|
||||
* @return array An array of all the tables in the database.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableList()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$type = 'table';
|
||||
|
||||
$query = $this->createQuery()
|
||||
->select('name')
|
||||
->from('sqlite_master')
|
||||
->where('type = :type')
|
||||
->bind(':type', $type)
|
||||
->order('name');
|
||||
|
||||
return $this->setQuery($query)->loadColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the database connector.
|
||||
*
|
||||
* @return string The database connector version.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return $this->setQuery('SELECT sqlite_version()')->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a database for use.
|
||||
*
|
||||
* @param string $database The name of the database to select for use.
|
||||
*
|
||||
* @return boolean True if the database was successfully selected.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function select($database)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection to use UTF-8 character encoding.
|
||||
*
|
||||
* Returns false automatically for the Oracle driver since
|
||||
* you can only set the character set when the connection
|
||||
* is created.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function setUtf()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks a table in the database.
|
||||
*
|
||||
* @param string $table The name of the table to unlock.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function lockTable($table)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a table in the database.
|
||||
*
|
||||
* @param string $oldTable The name of the table to be renamed
|
||||
* @param string $newTable The new name for the table.
|
||||
* @param string $backup Not used by Sqlite.
|
||||
* @param string $prefix Not used by Sqlite.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
|
||||
{
|
||||
$this->setQuery('ALTER TABLE ' . $oldTable . ' RENAME TO ' . $newTable)->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to truncate a table.
|
||||
*
|
||||
* @param string $table The table to truncate
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.2.1
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function truncateTable($table)
|
||||
{
|
||||
$this->setQuery('DELETE FROM ' . $this->quoteName($table))
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks tables in the database.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function unlockTables()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the PDO ODBC connector is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
return class_exists('\\PDO') && class_exists('\\SQLite3') && \in_array('sqlite', \PDO::getAvailableDrivers(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to commit a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, commit to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionCommit($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth <= 1) {
|
||||
parent::transactionCommit($toSavepoint);
|
||||
} else {
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to roll back a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, rollback to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionRollback($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth <= 1) {
|
||||
parent::transactionRollback($toSavepoint);
|
||||
} else {
|
||||
$savepoint = 'SP_' . ($this->transactionDepth - 1);
|
||||
$this->setQuery('ROLLBACK TO ' . $this->quoteName($savepoint))->execute();
|
||||
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to initialize a transaction.
|
||||
*
|
||||
* @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionStart($asSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$asSavepoint || !$this->transactionDepth) {
|
||||
parent::transactionStart($asSavepoint);
|
||||
} else {
|
||||
$savepoint = 'SP_' . $this->transactionDepth;
|
||||
$this->setQuery('SAVEPOINT ' . $this->quoteName($savepoint))->execute();
|
||||
|
||||
$this->transactionDepth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
269
libraries/vendor/joomla/database/src/Sqlite/SqliteQuery.php
vendored
Normal file
269
libraries/vendor/joomla/database/src/Sqlite/SqliteQuery.php
vendored
Normal file
@ -0,0 +1,269 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Sqlite;
|
||||
|
||||
use Joomla\Database\DatabaseQuery;
|
||||
use Joomla\Database\Pdo\PdoQuery;
|
||||
use Joomla\Database\Query\QueryElement;
|
||||
|
||||
/**
|
||||
* SQLite Query Building Class.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
class SqliteQuery extends PdoQuery
|
||||
{
|
||||
/**
|
||||
* Magic function to convert the query to a string.
|
||||
*
|
||||
* @return string The completed query.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
switch ($this->type) {
|
||||
case 'select':
|
||||
if ($this->selectRowNumber) {
|
||||
$orderBy = $this->selectRowNumber['orderBy'];
|
||||
$orderColumnAlias = $this->selectRowNumber['orderColumnAlias'];
|
||||
|
||||
$column = "ROW_NUMBER() AS $orderColumnAlias";
|
||||
|
||||
if ($this->select === null) {
|
||||
$query = PHP_EOL . 'SELECT 1'
|
||||
. (string) $this->from
|
||||
. (string) $this->where;
|
||||
} else {
|
||||
$tmpOffset = $this->offset;
|
||||
$tmpLimit = $this->limit;
|
||||
$this->offset = 0;
|
||||
$this->limit = 0;
|
||||
$tmpOrder = $this->order;
|
||||
$this->order = null;
|
||||
$query = parent::__toString();
|
||||
$column = "w.*, $column";
|
||||
$this->order = $tmpOrder;
|
||||
$this->offset = $tmpOffset;
|
||||
$this->limit = $tmpLimit;
|
||||
}
|
||||
|
||||
// Special sqlite query to count ROW_NUMBER
|
||||
$query = PHP_EOL . "SELECT $column"
|
||||
. PHP_EOL . "FROM ($query" . PHP_EOL . "ORDER BY $orderBy"
|
||||
. PHP_EOL . ') AS w,(SELECT ROW_NUMBER(0)) AS r'
|
||||
// Forbid to flatten subqueries.
|
||||
. ((string) $this->order ?: PHP_EOL . 'ORDER BY NULL');
|
||||
|
||||
return $this->processLimit($query, $this->limit, $this->offset);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'querySet':
|
||||
$query = $this->querySet;
|
||||
|
||||
if ($query->order || $query->limit || $query->offset) {
|
||||
// If ORDER BY or LIMIT statement exist then parentheses is required for the first query
|
||||
$query = PHP_EOL . "SELECT * FROM ($query)";
|
||||
}
|
||||
|
||||
if ($this->merge) {
|
||||
// Special case for merge
|
||||
foreach ($this->merge as $element) {
|
||||
$query .= (string) $element;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->order) {
|
||||
$query .= (string) $this->order;
|
||||
}
|
||||
|
||||
return $query;
|
||||
|
||||
case 'update':
|
||||
if ($this->join) {
|
||||
$table = $this->update->getElements();
|
||||
$table = $table[0];
|
||||
|
||||
$tableName = explode(' ', $table);
|
||||
$tableName = $tableName[0];
|
||||
|
||||
if ($this->columns === null) {
|
||||
$fields = $this->db->getTableColumns($tableName);
|
||||
|
||||
foreach ($fields as $key => $value) {
|
||||
$fields[$key] = $key;
|
||||
}
|
||||
|
||||
$this->columns = new QueryElement('()', $fields);
|
||||
}
|
||||
|
||||
$fields = $this->columns->getElements();
|
||||
$elements = $this->set->getElements();
|
||||
|
||||
foreach ($elements as $nameValue) {
|
||||
$setArray = explode(' = ', $nameValue, 2);
|
||||
|
||||
if ($setArray[0][0] === '`') {
|
||||
// Unquote column name
|
||||
$setArray[0] = substr($setArray[0], 1, -1);
|
||||
}
|
||||
|
||||
$fields[$setArray[0]] = $setArray[1];
|
||||
}
|
||||
|
||||
$select = new static($this->db);
|
||||
$select->select(array_values($fields))
|
||||
->from($table);
|
||||
|
||||
$select->join = $this->join;
|
||||
$select->where = $this->where;
|
||||
|
||||
return 'INSERT OR REPLACE INTO ' . $tableName
|
||||
. ' (' . implode(',', array_keys($fields)) . ')'
|
||||
. (string) $select;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::__toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of characters in a string.
|
||||
*
|
||||
* Note, use 'length' to find the number of bytes in a string.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->charLength('a'));
|
||||
*
|
||||
* @param string $field A value.
|
||||
* @param string|null $operator Comparison operator between charLength integer value and $condition
|
||||
* @param string|null $condition Integer value to compare charLength with.
|
||||
*
|
||||
* @return string The required char length call.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public function charLength($field, $operator = null, $condition = null)
|
||||
{
|
||||
$statement = 'length(' . $field . ')';
|
||||
|
||||
if ($operator !== null && $condition !== null) {
|
||||
$statement .= ' ' . $operator . ' ' . $condition;
|
||||
}
|
||||
|
||||
return $statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates an array of column names or values.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select($query->concatenate(array('a', 'b')));
|
||||
*
|
||||
* @param string[] $values An array of values to concatenate.
|
||||
* @param string|null $separator As separator to place between each value.
|
||||
*
|
||||
* @return string The concatenated values.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public function concatenate($values, $separator = null)
|
||||
{
|
||||
if ($separator !== null) {
|
||||
return implode(' || ' . $this->quote($separator) . ' || ', $values);
|
||||
}
|
||||
|
||||
return implode(' || ', $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to modify a query already in string format with the needed additions to make the query limited to a particular number of
|
||||
* results, or start at a particular offset.
|
||||
*
|
||||
* @param string $query The query in string format
|
||||
* @param integer $limit The limit for the result set
|
||||
* @param integer $offset The offset for the result set
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function processLimit($query, $limit, $offset = 0)
|
||||
{
|
||||
if ($limit > 0 || $offset > 0) {
|
||||
$query .= ' LIMIT ' . $offset . ', ' . $limit;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of the current row.
|
||||
*
|
||||
* Usage:
|
||||
* $query->select('id');
|
||||
* $query->selectRowNumber('ordering,publish_up DESC', 'new_ordering');
|
||||
* $query->from('#__content');
|
||||
*
|
||||
* @param string $orderBy An expression of ordering for window function.
|
||||
* @param string $orderColumnAlias An alias for new ordering column.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function selectRowNumber($orderBy, $orderColumnAlias)
|
||||
{
|
||||
$this->validateRowNumber($orderBy, $orderColumnAlias);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a query to UNION with the current query.
|
||||
*
|
||||
* Usage:
|
||||
* $query->union('SELECT name FROM #__foo')
|
||||
* $query->union('SELECT name FROM #__foo', true)
|
||||
*
|
||||
* @param DatabaseQuery|string $query The DatabaseQuery object or string to union.
|
||||
* @param boolean $distinct True to only return distinct rows from the union.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function union($query, $distinct = true)
|
||||
{
|
||||
// Set up the name with parentheses, the DISTINCT flag is redundant
|
||||
return $this->merge($distinct ? 'UNION SELECT * FROM ()' : 'UNION ALL SELECT * FROM ()', $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate function to get input values concatenated into a string, separated by delimiter
|
||||
*
|
||||
* Usage:
|
||||
* $query->groupConcat('id', ',');
|
||||
*
|
||||
* @param string $expression The expression to apply concatenation to, this may be a column name or complex SQL statement.
|
||||
* @param string $separator The delimiter of each concatenated value
|
||||
*
|
||||
* @return string Input values concatenated into a string, separated by delimiter
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function groupConcat($expression, $separator = ',')
|
||||
{
|
||||
return 'group_concat(' . $expression . ', ' . $this->quote($separator) . ')';
|
||||
}
|
||||
}
|
||||
931
libraries/vendor/joomla/database/src/Sqlsrv/SqlsrvDriver.php
vendored
Normal file
931
libraries/vendor/joomla/database/src/Sqlsrv/SqlsrvDriver.php
vendored
Normal file
@ -0,0 +1,931 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Sqlsrv;
|
||||
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\DatabaseEvents;
|
||||
use Joomla\Database\Event\ConnectionEvent;
|
||||
use Joomla\Database\Exception\ConnectionFailureException;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use Joomla\Database\Exception\PrepareStatementFailureException;
|
||||
use Joomla\Database\Exception\UnsupportedAdapterException;
|
||||
use Joomla\Database\StatementInterface;
|
||||
|
||||
/**
|
||||
* SQL Server Database Driver
|
||||
*
|
||||
* @link https://www.php.net/manual/en/book.sqlsrv.php
|
||||
* @since 1.0
|
||||
*/
|
||||
class SqlsrvDriver extends DatabaseDriver
|
||||
{
|
||||
/**
|
||||
* The name of the database driver.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
public $name = 'sqlsrv';
|
||||
|
||||
/**
|
||||
* The character(s) used to quote SQL statement names such as table names or field names, etc.
|
||||
*
|
||||
* If a single character string the same character is used for both sides of the quoted name, else the first character will be used for the
|
||||
* opening quote and the second for the closing quote.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $nameQuote = '[]';
|
||||
|
||||
/**
|
||||
* The null or zero representation of a timestamp for the database driver.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected $nullDate = '1900-01-01 00:00:00';
|
||||
|
||||
/**
|
||||
* The minimum supported database version.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0
|
||||
*/
|
||||
protected static $dbMinimum = '11.0.2100.60';
|
||||
|
||||
/**
|
||||
* Test to see if the SQLSRV connector is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
return \function_exists('sqlsrv_connect');
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $options List of options used to configure the connection
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __construct(array $options)
|
||||
{
|
||||
// Get some basic values from the options.
|
||||
$options['host'] = $options['host'] ?? 'localhost';
|
||||
$options['user'] = $options['user'] ?? '';
|
||||
$options['password'] = $options['password'] ?? '';
|
||||
$options['database'] = $options['database'] ?? '';
|
||||
$options['select'] = isset($options['select']) ? (bool) $options['select'] : true;
|
||||
|
||||
// Finalize initialisation
|
||||
parent::__construct($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the database if needed.
|
||||
*
|
||||
* @return void Returns void if the database connected successfully.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
if ($this->connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the SQLSRV extension for PHP is installed and enabled.
|
||||
if (!static::isSupported()) {
|
||||
throw new UnsupportedAdapterException('PHP extension sqlsrv_connect is not available.');
|
||||
}
|
||||
|
||||
// Build the connection configuration array.
|
||||
$config = [
|
||||
'Database' => $this->options['database'],
|
||||
'uid' => $this->options['user'],
|
||||
'pwd' => $this->options['password'],
|
||||
'CharacterSet' => 'UTF-8',
|
||||
'ReturnDatesAsStrings' => true,
|
||||
];
|
||||
|
||||
// Attempt to connect to the server.
|
||||
if (!($this->connection = @ sqlsrv_connect($this->options['host'], $config))) {
|
||||
throw new ConnectionFailureException('Could not connect to SQL Server');
|
||||
}
|
||||
|
||||
// Make sure that DB warnings are not returned as errors.
|
||||
sqlsrv_configure('WarningsReturnAsErrors', 0);
|
||||
|
||||
// If auto-select is enabled select the given database.
|
||||
if ($this->options['select'] && !empty($this->options['database'])) {
|
||||
$this->select($this->options['database']);
|
||||
}
|
||||
|
||||
$this->dispatchEvent(new ConnectionEvent(DatabaseEvents::POST_CONNECT, $this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects the database.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
// Close the connection.
|
||||
if (\is_resource($this->connection)) {
|
||||
sqlsrv_close($this->connection);
|
||||
}
|
||||
|
||||
parent::disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table constraints
|
||||
*
|
||||
* @param string $tableName The name of the database table.
|
||||
*
|
||||
* @return array Any constraints available for the table.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function getTableConstraints($tableName)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return $this->setQuery('SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = ' . $this->quote($tableName))
|
||||
->loadColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename constraints.
|
||||
*
|
||||
* @param array $constraints Array(strings) of table constraints
|
||||
* @param string $prefix A string
|
||||
* @param string $backup A string
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function renameConstraints($constraints = [], $prefix = null, $backup = null)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
foreach ($constraints as $constraint) {
|
||||
$this->setQuery('sp_rename ' . $constraint . ',' . str_replace($prefix, $backup, $constraint))
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to escape a string for usage in an SQL statement.
|
||||
*
|
||||
* The escaping for MSSQL isn't handled in the driver though that would be nice. Because of this we need to handle the escaping ourselves.
|
||||
*
|
||||
* @param string $text The string to be escaped.
|
||||
* @param boolean $extra Optional parameter to provide extra escaping.
|
||||
*
|
||||
* @return string The escaped string.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function escape($text, $extra = false)
|
||||
{
|
||||
if (\is_int($text)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
if (\is_float($text)) {
|
||||
// Force the dot as a decimal point.
|
||||
return str_replace(',', '.', $text);
|
||||
}
|
||||
|
||||
$result = str_replace("'", "''", $text);
|
||||
|
||||
// SQL Server does not accept NULL byte in query string
|
||||
$result = str_replace("\0", "' + CHAR(0) + N'", $result);
|
||||
|
||||
// Fix for SQL Sever escape sequence, see https://support.microsoft.com/en-us/kb/164291
|
||||
$result = str_replace(
|
||||
["\\\n", "\\\r", "\\\\\r\r\n"],
|
||||
["\\\\\n\n", "\\\\\r\r", "\\\\\r\n\r\n"],
|
||||
$result
|
||||
);
|
||||
|
||||
if ($extra) {
|
||||
// Escape special chars
|
||||
$result = str_replace(
|
||||
['[', '_', '%'],
|
||||
['[[]', '[_]', '[%]'],
|
||||
$result
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes and optionally escapes a string to database requirements for use in database queries.
|
||||
*
|
||||
* @param mixed $text A string or an array of strings to quote.
|
||||
* @param boolean $escape True (default) to escape the string, false to leave it unchanged.
|
||||
*
|
||||
* @return string The quoted input string.
|
||||
*
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public function quote($text, $escape = true)
|
||||
{
|
||||
if (\is_array($text)) {
|
||||
return parent::quote($text, $escape);
|
||||
}
|
||||
|
||||
// To support unicode on MSSQL we have to add prefix N
|
||||
return 'N\'' . ($escape ? $this->escape($text) : $text) . '\'';
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes a binary string to database requirements for use in database queries.
|
||||
*
|
||||
* @param string $data A binary string to quote.
|
||||
*
|
||||
* @return string The binary quoted input string.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function quoteBinary($data)
|
||||
{
|
||||
// ODBC syntax for hexadecimal literals
|
||||
return '0x' . bin2hex($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the connection to the server is active.
|
||||
*
|
||||
* @return boolean True if connected to the database engine.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function connected()
|
||||
{
|
||||
// TODO: Run a blank query here
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops a table from the database.
|
||||
*
|
||||
* @param string $table The name of the database table to drop.
|
||||
* @param boolean $ifExists Optionally specify that the table must exist before it is dropped.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function dropTable($table, $ifExists = true)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if ($ifExists) {
|
||||
$this->setQuery(
|
||||
'IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '
|
||||
. $this->quote($table) . ') DROP TABLE ' . $table
|
||||
);
|
||||
} else {
|
||||
$this->setQuery('DROP TABLE ' . $table);
|
||||
}
|
||||
|
||||
$this->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database collation in use by sampling a text field of a table in the database.
|
||||
*
|
||||
* @return string|boolean The collation in use by the database or boolean false if not supported.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getCollation()
|
||||
{
|
||||
// TODO: Not fake this
|
||||
return 'MSSQL UTF-8 (UCS2)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database connection collation in use by sampling a text field of a table in the database.
|
||||
*
|
||||
* @return string|boolean The collation in use by the database connection (string) or boolean false if not supported.
|
||||
*
|
||||
* @since 1.6.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getConnectionCollation()
|
||||
{
|
||||
// TODO: Not fake this
|
||||
return 'MSSQL UTF-8 (UCS2)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database encryption details (cipher and protocol) in use.
|
||||
*
|
||||
* @return string The database encryption details.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getConnectionEncryption(): string
|
||||
{
|
||||
// TODO: Not fake this
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test if the database TLS connections encryption are supported.
|
||||
*
|
||||
* @return boolean Whether the database supports TLS connections encryption.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function isConnectionEncryptionSupported(): bool
|
||||
{
|
||||
// TODO: Not fake this
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves field information about the given tables.
|
||||
*
|
||||
* @param mixed $table A table name
|
||||
* @param boolean $typeOnly True to only return field types.
|
||||
*
|
||||
* @return array An array of fields.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableColumns($table, $typeOnly = true)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$table_temp = $this->replacePrefix((string) $table);
|
||||
|
||||
// Set the query to get the table fields statement.
|
||||
$this->setQuery(
|
||||
'SELECT column_name as Field, data_type as Type, is_nullable as \'Null\', column_default as \'Default\'' .
|
||||
' FROM information_schema.columns WHERE table_name = ' . $this->quote($table_temp)
|
||||
);
|
||||
$fields = $this->loadObjectList();
|
||||
|
||||
// If we only want the type as the value add just that to the list.
|
||||
if ($typeOnly) {
|
||||
foreach ($fields as $field) {
|
||||
$result[$field->Field] = preg_replace('/[(0-9)]/', '', $field->Type);
|
||||
}
|
||||
} else {
|
||||
// If we want the whole field data object add that to the list.
|
||||
foreach ($fields as $field) {
|
||||
$field->Default = preg_replace("/(^(\(\(|\('|\(N'|\()|(('\)|(?<!\()\)\)|\))$))/i", '', $field->Default);
|
||||
$result[$field->Field] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the table CREATE statement that creates the given tables.
|
||||
*
|
||||
* This is unsupported by MSSQL.
|
||||
*
|
||||
* @param mixed $tables A table name or a list of table names.
|
||||
*
|
||||
* @return array A list of the create SQL for the tables.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableCreate($tables)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of keys for a table.
|
||||
*
|
||||
* @param string $table The name of the table.
|
||||
*
|
||||
* @return array An array of the column specification for the table.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableKeys($table)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// TODO To implement.
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of all tables in the database.
|
||||
*
|
||||
* @return array An array of all the tables in the database.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getTableList()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Set the query to get the tables statement.
|
||||
return $this->setQuery('SELECT name FROM ' . $this->getDatabase() . '.sys.Tables WHERE type = \'U\';')->loadColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the database connector.
|
||||
*
|
||||
* @return string The database connector version.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$version = sqlsrv_server_info($this->connection);
|
||||
|
||||
return $version['SQLServerVersion'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a row into a table based on an object's properties.
|
||||
*
|
||||
* @param string $table The name of the database table to insert into.
|
||||
* @param object $object A reference to an object whose public properties match the table fields.
|
||||
* @param string $key The name of the primary key. If provided the object property is updated.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function insertObject($table, &$object, $key = null)
|
||||
{
|
||||
$fields = [];
|
||||
$values = [];
|
||||
$tableColumns = $this->getTableColumns($table);
|
||||
$statement = 'INSERT INTO ' . $this->quoteName($table) . ' (%s) VALUES (%s)';
|
||||
|
||||
foreach (get_object_vars($object) as $k => $v) {
|
||||
// Skip columns that don't exist in the table.
|
||||
if (!\array_key_exists($k, $tableColumns)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only process non-null scalars.
|
||||
if (\is_array($v) || \is_object($v) || $v === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->checkFieldExists($table, $k)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($k[0] === '_') {
|
||||
// Internal field
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($k === $key && $key == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fields[] = $this->quoteName($k);
|
||||
$values[] = $this->quote($v);
|
||||
}
|
||||
|
||||
// Set the query and execute the insert.
|
||||
$this->setQuery(sprintf($statement, implode(',', $fields), implode(',', $values)))->execute();
|
||||
|
||||
$id = $this->insertid();
|
||||
|
||||
if ($key && $id) {
|
||||
$object->$key = $id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the auto-incremented value from the last INSERT statement.
|
||||
*
|
||||
* @return integer The value of the auto-increment field from the last inserted row.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function insertid()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// TODO: SELECT IDENTITY
|
||||
$this->setQuery('SELECT @@IDENTITY');
|
||||
|
||||
return (int) $this->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the SQL statement.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Take a local copy so that we don't modify the original query and cause issues later
|
||||
$sql = $this->replacePrefix((string) $this->sql);
|
||||
|
||||
// Increment the query counter.
|
||||
$this->count++;
|
||||
|
||||
// Get list of bounded parameters
|
||||
$bounded =& $this->sql->getBounded();
|
||||
|
||||
// If there is a monitor registered, let it know we are starting this query
|
||||
if ($this->monitor) {
|
||||
$this->monitor->startQuery($sql, $bounded);
|
||||
}
|
||||
|
||||
// Execute the query.
|
||||
$this->executed = false;
|
||||
|
||||
// Bind the variables
|
||||
foreach ($bounded as $key => $obj) {
|
||||
$this->statement->bindParam($key, $obj->value, $obj->dataType);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->executed = $this->statement->execute();
|
||||
|
||||
// If there is a monitor registered, let it know we have finished this query
|
||||
if ($this->monitor) {
|
||||
$this->monitor->stopQuery();
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (ExecutionFailureException $exception) {
|
||||
// If there is a monitor registered, let it know we have finished this query
|
||||
if ($this->monitor) {
|
||||
$this->monitor->stopQuery();
|
||||
}
|
||||
|
||||
// Check if the server was disconnected.
|
||||
if (!$this->connected()) {
|
||||
try {
|
||||
// Attempt to reconnect.
|
||||
$this->connection = null;
|
||||
$this->connect();
|
||||
} catch (ConnectionFailureException $e) {
|
||||
// If connect fails, ignore that exception and throw the normal exception.
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
// Since we were able to reconnect, run the query again.
|
||||
return $this->execute();
|
||||
}
|
||||
|
||||
// Throw the normal query exception.
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function replaces a string identifier with the configured table prefix.
|
||||
*
|
||||
* @param string $sql The SQL statement to prepare.
|
||||
* @param string $prefix The table prefix.
|
||||
*
|
||||
* @return string The processed SQL statement.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function replacePrefix($sql, $prefix = '#__')
|
||||
{
|
||||
$escaped = false;
|
||||
$startPos = 0;
|
||||
$quoteChar = '';
|
||||
$literal = '';
|
||||
|
||||
$sql = trim($sql);
|
||||
$n = \strlen($sql);
|
||||
|
||||
while ($startPos < $n) {
|
||||
$ip = strpos($sql, $prefix, $startPos);
|
||||
|
||||
if ($ip === false) {
|
||||
break;
|
||||
}
|
||||
|
||||
$j = strpos($sql, "N'", $startPos);
|
||||
$k = strpos($sql, '"', $startPos);
|
||||
|
||||
if (($k !== false) && (($k < $j) || ($j === false))) {
|
||||
$quoteChar = '"';
|
||||
$j = $k;
|
||||
} else {
|
||||
$quoteChar = "'";
|
||||
}
|
||||
|
||||
if ($j === false) {
|
||||
$j = $n;
|
||||
}
|
||||
|
||||
$literal .= str_replace($prefix, $this->tablePrefix, substr($sql, $startPos, $j - $startPos));
|
||||
$startPos = $j;
|
||||
|
||||
$j = $startPos + 1;
|
||||
|
||||
if ($j >= $n) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Quote comes first, find end of quote
|
||||
while (true) {
|
||||
$k = strpos($sql, $quoteChar, $j);
|
||||
$escaped = false;
|
||||
|
||||
if ($k === false) {
|
||||
break;
|
||||
}
|
||||
|
||||
$l = $k - 1;
|
||||
|
||||
while ($l >= 0 && $sql[$l] === '\\') {
|
||||
$l--;
|
||||
$escaped = !$escaped;
|
||||
}
|
||||
|
||||
if ($escaped) {
|
||||
$j = $k + 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($k === false) {
|
||||
// Error in the query - no end quote; ignore it
|
||||
break;
|
||||
}
|
||||
|
||||
$literal .= substr($sql, $startPos, $k - $startPos + 1);
|
||||
$startPos = $k + 1;
|
||||
}
|
||||
|
||||
if ($startPos < $n) {
|
||||
$literal .= substr($sql, $startPos, $n - $startPos);
|
||||
}
|
||||
|
||||
return $literal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a database for use.
|
||||
*
|
||||
* @param string $database The name of the database to select for use.
|
||||
*
|
||||
* @return boolean True if the database was successfully selected.
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws ConnectionFailureException
|
||||
*/
|
||||
public function select($database)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$database) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sqlsrv_query($this->connection, 'USE [' . $database . ']', null, ['scrollable' => \SQLSRV_CURSOR_STATIC])) {
|
||||
throw new ConnectionFailureException('Could not connect to database');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection to use UTF-8 character encoding.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function setUtf()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to commit a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, commit to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionCommit($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth <= 1) {
|
||||
$this->setQuery('COMMIT TRANSACTION')->execute();
|
||||
|
||||
$this->transactionDepth = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to roll back a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, rollback to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionRollback($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth <= 1) {
|
||||
$this->setQuery('ROLLBACK TRANSACTION')->execute();
|
||||
|
||||
$this->transactionDepth = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$savepoint = 'SP_' . ($this->transactionDepth - 1);
|
||||
$this->setQuery('ROLLBACK TRANSACTION ' . $this->quoteName($savepoint))->execute();
|
||||
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to initialize a transaction.
|
||||
*
|
||||
* @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function transactionStart($asSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$asSavepoint || !$this->transactionDepth) {
|
||||
$this->setQuery('BEGIN TRANSACTION')->execute();
|
||||
|
||||
$this->transactionDepth = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$savepoint = 'SP_' . $this->transactionDepth;
|
||||
$this->setQuery('BEGIN TRANSACTION ' . $this->quoteName($savepoint))->execute();
|
||||
|
||||
$this->transactionDepth++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check and see if a field exists in a table.
|
||||
*
|
||||
* @param string $table The table in which to verify the field.
|
||||
* @param string $field The field to verify.
|
||||
*
|
||||
* @return boolean True if the field exists in the table.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
protected function checkFieldExists($table, $field)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$table = $this->replacePrefix((string) $table);
|
||||
$this->setQuery(
|
||||
"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '$table' AND COLUMN_NAME = '$field' ORDER BY ORDINAL_POSITION"
|
||||
);
|
||||
|
||||
return (bool) $this->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a SQL statement for execution
|
||||
*
|
||||
* @param string $query The SQL query to be prepared.
|
||||
*
|
||||
* @return StatementInterface
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws PrepareStatementFailureException
|
||||
*/
|
||||
protected function prepareStatement(string $query): StatementInterface
|
||||
{
|
||||
return new SqlsrvStatement($this->connection, $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a table in the database.
|
||||
*
|
||||
* @param string $oldTable The name of the table to be renamed
|
||||
* @param string $newTable The new name for the table.
|
||||
* @param string $backup Table prefix
|
||||
* @param string $prefix For the table - used to rename constraints in non-mysql databases
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
|
||||
{
|
||||
$constraints = [];
|
||||
|
||||
if ($prefix !== null && $backup !== null) {
|
||||
$constraints = $this->getTableConstraints($oldTable);
|
||||
}
|
||||
|
||||
if (!empty($constraints)) {
|
||||
$this->renameConstraints($constraints, $prefix, $backup);
|
||||
}
|
||||
|
||||
$this->setQuery("sp_rename '" . $oldTable . "', '" . $newTable . "'");
|
||||
|
||||
$this->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks a table in the database.
|
||||
*
|
||||
* @param string $tableName The name of the table to lock.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function lockTable($tableName)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks tables in the database.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 1.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function unlockTables()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
1078
libraries/vendor/joomla/database/src/Sqlsrv/SqlsrvQuery.php
vendored
Normal file
1078
libraries/vendor/joomla/database/src/Sqlsrv/SqlsrvQuery.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
546
libraries/vendor/joomla/database/src/Sqlsrv/SqlsrvStatement.php
vendored
Normal file
546
libraries/vendor/joomla/database/src/Sqlsrv/SqlsrvStatement.php
vendored
Normal file
@ -0,0 +1,546 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database\Sqlsrv;
|
||||
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use Joomla\Database\Exception\PrepareStatementFailureException;
|
||||
use Joomla\Database\FetchMode;
|
||||
use Joomla\Database\FetchOrientation;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Database\StatementInterface;
|
||||
|
||||
/**
|
||||
* SQL Server Database Statement.
|
||||
*
|
||||
* This class is modeled on \Doctrine\DBAL\Driver\SQLSrv\SQLSrvStatement
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class SqlsrvStatement implements StatementInterface
|
||||
{
|
||||
/**
|
||||
* The database connection resource.
|
||||
*
|
||||
* @var resource
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The default fetch mode for the statement.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $defaultFetchStyle = FetchMode::MIXED;
|
||||
|
||||
/**
|
||||
* The default class to use for building object result sets.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $defaultObjectClass = \stdClass::class;
|
||||
|
||||
/**
|
||||
* Mapping array converting fetch modes to the native engine type.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $fetchMap = [
|
||||
FetchMode::MIXED => SQLSRV_FETCH_BOTH,
|
||||
FetchMode::ASSOCIATIVE => SQLSRV_FETCH_ASSOC,
|
||||
FetchMode::NUMERIC => SQLSRV_FETCH_NUMERIC,
|
||||
];
|
||||
|
||||
/**
|
||||
* The query string being prepared.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* Internal tracking flag to set whether there is a result set available for processing
|
||||
*
|
||||
* @var boolean
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $result = false;
|
||||
|
||||
/**
|
||||
* The prepared statement.
|
||||
*
|
||||
* @var resource
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $statement;
|
||||
|
||||
/**
|
||||
* Bound parameter types.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $typesKeyMapping;
|
||||
|
||||
/**
|
||||
* References to the variables bound as statement parameters.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private $bindedValues = [];
|
||||
|
||||
/**
|
||||
* Mapping between named parameters and position in query.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $parameterKeyMapping;
|
||||
|
||||
/**
|
||||
* Mapping array for parameter types.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected $parameterTypeMapping = [
|
||||
ParameterType::BOOLEAN => ParameterType::BOOLEAN,
|
||||
ParameterType::INTEGER => ParameterType::INTEGER,
|
||||
ParameterType::LARGE_OBJECT => ParameterType::LARGE_OBJECT,
|
||||
ParameterType::NULL => ParameterType::NULL,
|
||||
ParameterType::STRING => ParameterType::STRING,
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param resource $connection The database connection resource
|
||||
* @param string $query The query this statement will process
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @throws PrepareStatementFailureException
|
||||
*/
|
||||
public function __construct($connection, string $query)
|
||||
{
|
||||
// Initial parameter types for prepared statements
|
||||
$this->parameterTypeMapping = [
|
||||
ParameterType::BOOLEAN => SQLSRV_PHPTYPE_INT,
|
||||
ParameterType::INTEGER => SQLSRV_PHPTYPE_INT,
|
||||
ParameterType::LARGE_OBJECT => SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY),
|
||||
ParameterType::NULL => SQLSRV_PHPTYPE_NULL,
|
||||
ParameterType::STRING => SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
|
||||
];
|
||||
|
||||
$this->connection = $connection;
|
||||
$this->query = $this->prepareParameterKeyMapping($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace named parameters with numbered parameters
|
||||
*
|
||||
* @param string $sql The SQL statement to prepare.
|
||||
*
|
||||
* @return string The processed SQL statement.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function prepareParameterKeyMapping($sql)
|
||||
{
|
||||
$escaped = false;
|
||||
$startPos = 0;
|
||||
$quoteChar = '';
|
||||
$literal = '';
|
||||
$mapping = [];
|
||||
$replace = [];
|
||||
$matches = [];
|
||||
$pattern = '/([:][a-zA-Z0-9_]+)/';
|
||||
|
||||
if (!preg_match($pattern, $sql, $matches)) {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
$sql = trim($sql);
|
||||
$n = \strlen($sql);
|
||||
|
||||
while ($startPos < $n) {
|
||||
if (!preg_match($pattern, $sql, $matches, 0, $startPos)) {
|
||||
break;
|
||||
}
|
||||
|
||||
$j = strpos($sql, "'", $startPos);
|
||||
$k = strpos($sql, '"', $startPos);
|
||||
|
||||
if (($k !== false) && (($k < $j) || ($j === false))) {
|
||||
$quoteChar = '"';
|
||||
$j = $k;
|
||||
} else {
|
||||
$quoteChar = "'";
|
||||
}
|
||||
|
||||
if ($j === false) {
|
||||
$j = $n;
|
||||
}
|
||||
|
||||
// Search for named prepared parameters and replace it with ? and save its position
|
||||
$substring = substr($sql, $startPos, $j - $startPos);
|
||||
|
||||
if (preg_match_all($pattern, $substring, $matches, PREG_PATTERN_ORDER + PREG_OFFSET_CAPTURE)) {
|
||||
foreach ($matches[0] as $i => $match) {
|
||||
if ($i === 0) {
|
||||
$literal .= substr($substring, 0, $match[1]);
|
||||
}
|
||||
|
||||
$mapping[$match[0]] = \count($mapping);
|
||||
$endOfPlaceholder = $match[1] + strlen($match[0]);
|
||||
$beginOfNextPlaceholder = $matches[0][$i + 1][1] ?? strlen($substring);
|
||||
$beginOfNextPlaceholder -= $endOfPlaceholder;
|
||||
$literal .= '?' . substr($substring, $endOfPlaceholder, $beginOfNextPlaceholder);
|
||||
}
|
||||
} else {
|
||||
$literal .= $substring;
|
||||
}
|
||||
|
||||
$startPos = $j;
|
||||
$j++;
|
||||
|
||||
if ($j >= $n) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Quote comes first, find end of quote
|
||||
while (true) {
|
||||
$k = strpos($sql, $quoteChar, $j);
|
||||
$escaped = false;
|
||||
|
||||
if ($k === false) {
|
||||
break;
|
||||
}
|
||||
|
||||
$l = $k - 1;
|
||||
|
||||
while ($l >= 0 && $sql[$l] === '\\') {
|
||||
$l--;
|
||||
$escaped = !$escaped;
|
||||
}
|
||||
|
||||
if ($escaped) {
|
||||
$j = $k + 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($k === false) {
|
||||
// Error in the query - no end quote; ignore it
|
||||
break;
|
||||
}
|
||||
|
||||
$literal .= substr($sql, $startPos, $k - $startPos + 1);
|
||||
$startPos = $k + 1;
|
||||
}
|
||||
|
||||
if ($startPos < $n) {
|
||||
$literal .= substr($sql, $startPos, $n - $startPos);
|
||||
}
|
||||
|
||||
$this->parameterKeyMapping = $mapping;
|
||||
|
||||
return $literal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a parameter to the specified variable name.
|
||||
*
|
||||
* @param string|integer $parameter Parameter identifier. For a prepared statement using named placeholders, this will be a parameter
|
||||
* name of the form `:name`. For a prepared statement using question mark placeholders, this will be
|
||||
* the 1-indexed position of the parameter.
|
||||
* @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter.
|
||||
* @param string $dataType Constant corresponding to a SQL datatype, this should be the processed type from the QueryInterface.
|
||||
* @param ?integer $length The length of the variable. Usually required for OUTPUT parameters.
|
||||
* @param ?array $driverOptions Optional driver options to be used.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function bindParam($parameter, &$variable, string $dataType = ParameterType::STRING, ?int $length = null, ?array $driverOptions = null)
|
||||
{
|
||||
$this->bindedValues[$parameter] =& $variable;
|
||||
|
||||
// Validate parameter type
|
||||
if (!isset($this->parameterTypeMapping[$dataType])) {
|
||||
throw new \InvalidArgumentException(sprintf('Unsupported parameter type `%s`', $dataType));
|
||||
}
|
||||
|
||||
$this->typesKeyMapping[$parameter] = $this->parameterTypeMapping[$dataType];
|
||||
|
||||
$this->statement = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a value to the specified variable.
|
||||
*
|
||||
* @param string|integer $parameter Parameter identifier. For a prepared statement using named placeholders, this will be a parameter
|
||||
* name of the form `:name`. For a prepared statement using question mark placeholders, this will be
|
||||
* the 1-indexed position of the parameter.
|
||||
* @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter.
|
||||
* @param string $dataType Constant corresponding to a SQL datatype, this should be the processed type from the QueryInterface.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private function bindValue($parameter, $variable, $dataType = ParameterType::STRING)
|
||||
{
|
||||
$this->bindedValues[$parameter] = $variable;
|
||||
$this->typesKeyMapping[$parameter] = $dataType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the cursor, enabling the statement to be executed again.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function closeCursor(): void
|
||||
{
|
||||
if (!$this->result || !\is_resource($this->statement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Emulate freeing the result fetching and discarding rows, similarly to what PDO does in this case
|
||||
while (sqlsrv_fetch($this->statement)) {
|
||||
// Do nothing (see above)
|
||||
}
|
||||
|
||||
$this->result = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the SQLSTATE associated with the last operation on the statement handle.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function errorCode()
|
||||
{
|
||||
$errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
|
||||
|
||||
if ($errors) {
|
||||
return $errors[0]['code'];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches extended error information associated with the last operation on the statement handle.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function errorInfo()
|
||||
{
|
||||
return sqlsrv_errors(SQLSRV_ERR_ERRORS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a prepared statement
|
||||
*
|
||||
* @param array|null $parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function execute(?array $parameters = null)
|
||||
{
|
||||
if (empty($this->bindedValues) && $parameters !== null) {
|
||||
$hasZeroIndex = array_key_exists(0, $parameters);
|
||||
|
||||
foreach ($parameters as $key => $val) {
|
||||
$key = ($hasZeroIndex && is_numeric($key)) ? $key + 1 : $key;
|
||||
$this->bindValue($key, $val);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->statement) {
|
||||
$this->statement = $this->prepare();
|
||||
}
|
||||
|
||||
if (!sqlsrv_execute($this->statement)) {
|
||||
$errors = $this->errorInfo();
|
||||
|
||||
throw new ExecutionFailureException($this->query, $errors[0]['message'], $errors[0]['code']);
|
||||
}
|
||||
|
||||
$this->result = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the next row from a result set
|
||||
*
|
||||
* @param integer|null $fetchStyle Controls how the next row will be returned to the caller. This value must be one of the
|
||||
* FetchMode constants, defaulting to value of FetchMode::MIXED.
|
||||
* @param integer $cursorOrientation For a StatementInterface object representing a scrollable cursor, this value determines which row
|
||||
* will be returned to the caller. This value must be one of the FetchOrientation constants,
|
||||
* defaulting to FetchOrientation::NEXT.
|
||||
* @param integer $cursorOffset For a StatementInterface object representing a scrollable cursor for which the cursorOrientation
|
||||
* parameter is set to FetchOrientation::ABS, this value specifies the absolute number of the row in
|
||||
* the result set that shall be fetched. For a StatementInterface object representing a scrollable
|
||||
* cursor for which the cursorOrientation parameter is set to FetchOrientation::REL, this value
|
||||
* specifies the row to fetch relative to the cursor position before `fetch()` was called.
|
||||
*
|
||||
* @return mixed The return value of this function on success depends on the fetch type. In all cases, boolean false is returned on failure.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function fetch(?int $fetchStyle = null, int $cursorOrientation = FetchOrientation::NEXT, int $cursorOffset = 0)
|
||||
{
|
||||
if (!$this->result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$fetchStyle = $fetchStyle ?: $this->defaultFetchStyle;
|
||||
|
||||
if ($fetchStyle === FetchMode::COLUMN) {
|
||||
return $this->fetchColumn();
|
||||
}
|
||||
|
||||
if (isset($this->fetchMap[$fetchStyle])) {
|
||||
return sqlsrv_fetch_array($this->statement, $this->fetchMap[$fetchStyle]) ?: false;
|
||||
}
|
||||
|
||||
if (\in_array($fetchStyle, [FetchMode::STANDARD_OBJECT, FetchMode::CUSTOM_OBJECT], true)) {
|
||||
return sqlsrv_fetch_object($this->statement, $this->defaultObjectClass) ?: false;
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("Unknown fetch type '{$fetchStyle}'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single column from the next row of a result set
|
||||
*
|
||||
* @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row.
|
||||
* If no value is supplied, the first column is retrieved.
|
||||
*
|
||||
* @return mixed Returns a single column from the next row of a result set or boolean false if there are no more rows.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function fetchColumn($columnIndex = 0)
|
||||
{
|
||||
$row = $this->fetch(FetchMode::NUMERIC);
|
||||
|
||||
if ($row === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $row[$columnIndex] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the SQL Server statement resource for execution
|
||||
*
|
||||
* @return resource
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private function prepare()
|
||||
{
|
||||
$params = [];
|
||||
$options = [];
|
||||
|
||||
foreach ($this->bindedValues as $key => &$value) {
|
||||
$variable = [
|
||||
&$value,
|
||||
SQLSRV_PARAM_IN,
|
||||
];
|
||||
|
||||
if ($this->typesKeyMapping[$key] === $this->parameterTypeMapping[ParameterType::LARGE_OBJECT]) {
|
||||
$variable[] = $this->typesKeyMapping[$key];
|
||||
$variable[] = SQLSRV_SQLTYPE_VARBINARY('max');
|
||||
}
|
||||
|
||||
if (isset($this->parameterKeyMapping[$key])) {
|
||||
$params[$this->parameterKeyMapping[$key]] = $variable;
|
||||
} else {
|
||||
$params[] = $variable;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup referenced variable
|
||||
unset($value);
|
||||
|
||||
// SQLSRV Function sqlsrv_num_rows requires a static or keyset cursor.
|
||||
if (strncmp(strtoupper(ltrim($this->query)), 'SELECT', \strlen('SELECT')) === 0) {
|
||||
$options = ['Scrollable' => SQLSRV_CURSOR_KEYSET];
|
||||
}
|
||||
|
||||
$statement = sqlsrv_prepare($this->connection, $this->query, $params, $options);
|
||||
|
||||
if (!$statement) {
|
||||
$errors = $this->errorInfo();
|
||||
|
||||
throw new PrepareStatementFailureException($errors[0]['message'], $errors[0]['code']);
|
||||
}
|
||||
|
||||
return $statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of rows affected by the last SQL statement.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function rowCount(): int
|
||||
{
|
||||
if (strncmp(strtoupper(ltrim($this->query)), 'SELECT', \strlen('SELECT')) === 0) {
|
||||
return sqlsrv_num_rows($this->statement);
|
||||
}
|
||||
|
||||
return sqlsrv_rows_affected($this->statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fetch mode to use while iterating this statement.
|
||||
*
|
||||
* @param integer $fetchMode The fetch mode, must be one of the FetchMode constants.
|
||||
* @param mixed ...$args Optional mode-specific arguments.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function setFetchMode(int $fetchMode, ...$args): void
|
||||
{
|
||||
$this->defaultFetchStyle = $fetchMode;
|
||||
|
||||
if (isset($args[0])) {
|
||||
$this->defaultObjectClass = $args[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
116
libraries/vendor/joomla/database/src/StatementInterface.php
vendored
Normal file
116
libraries/vendor/joomla/database/src/StatementInterface.php
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Interface defining a query statement.
|
||||
*
|
||||
* This interface is a partial standalone implementation of PDOStatement.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface StatementInterface
|
||||
{
|
||||
/**
|
||||
* Binds a parameter to the specified variable name.
|
||||
*
|
||||
* @param string|integer $parameter Parameter identifier. For a prepared statement using named placeholders, this will be a parameter
|
||||
* name of the form `:name`. For a prepared statement using question mark placeholders, this will be
|
||||
* the 1-indexed position of the parameter.
|
||||
* @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter.
|
||||
* @param string $dataType Constant corresponding to a SQL datatype, this should be the processed type from the QueryInterface.
|
||||
* @param ?integer $length The length of the variable. Usually required for OUTPUT parameters.
|
||||
* @param ?array $driverOptions Optional driver options to be used.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function bindParam($parameter, &$variable, string $dataType = ParameterType::STRING, ?int $length = null, ?array $driverOptions = null);
|
||||
|
||||
/**
|
||||
* Closes the cursor, enabling the statement to be executed again.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function closeCursor(): void;
|
||||
|
||||
/**
|
||||
* Fetches the SQLSTATE associated with the last operation on the statement handle.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function errorCode();
|
||||
|
||||
/**
|
||||
* Fetches extended error information associated with the last operation on the statement handle.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function errorInfo();
|
||||
|
||||
/**
|
||||
* Executes a prepared statement
|
||||
*
|
||||
* @param array|null $parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function execute(?array $parameters = null);
|
||||
|
||||
/**
|
||||
* Fetches the next row from a result set
|
||||
*
|
||||
* @param integer|null $fetchStyle Controls how the next row will be returned to the caller. This value must be one of the
|
||||
* FetchMode constants, defaulting to value of FetchMode::MIXED.
|
||||
* @param integer $cursorOrientation For a StatementInterface object representing a scrollable cursor, this value determines which row
|
||||
* will be returned to the caller. This value must be one of the FetchOrientation constants,
|
||||
* defaulting to FetchOrientation::NEXT.
|
||||
* @param integer $cursorOffset For a StatementInterface object representing a scrollable cursor for which the cursorOrientation
|
||||
* parameter is set to FetchOrientation::ABS, this value specifies the absolute number of the row in
|
||||
* the result set that shall be fetched. For a StatementInterface object representing a scrollable
|
||||
* cursor for which the cursorOrientation parameter is set to FetchOrientation::REL, this value
|
||||
* specifies the row to fetch relative to the cursor position before `fetch()` was called.
|
||||
*
|
||||
* @return mixed The return value of this function on success depends on the fetch type. In all cases, boolean false is returned on failure.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function fetch(?int $fetchStyle = null, int $cursorOrientation = FetchOrientation::NEXT, int $cursorOffset = 0);
|
||||
|
||||
/**
|
||||
* Returns the number of rows affected by the last SQL statement.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function rowCount(): int;
|
||||
|
||||
/**
|
||||
* Sets the fetch mode to use while iterating this statement.
|
||||
*
|
||||
* @param integer $fetchMode The fetch mode, must be one of the FetchMode constants.
|
||||
* @param mixed ...$args Optional mode-specific arguments.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function setFetchMode(int $fetchMode, ...$args): void;
|
||||
}
|
||||
40
libraries/vendor/joomla/database/src/UTF8MB4SupportInterface.php
vendored
Normal file
40
libraries/vendor/joomla/database/src/UTF8MB4SupportInterface.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Part of the Joomla Framework Database Package
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
namespace Joomla\Database;
|
||||
|
||||
/**
|
||||
* Interface defining a driver which has support for the MySQL `utf8mb4` character set
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface UTF8MB4SupportInterface
|
||||
{
|
||||
/**
|
||||
* Automatically downgrade a CREATE TABLE or ALTER TABLE query from utf8mb4 (UTF-8 Multibyte) to plain utf8.
|
||||
*
|
||||
* Used when the server doesn't support UTF-8 Multibyte.
|
||||
*
|
||||
* @param string $query The query to convert
|
||||
*
|
||||
* @return string The converted query
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function convertUtf8mb4QueryToUtf8($query);
|
||||
|
||||
/**
|
||||
* Check whether the database engine supports the UTF-8 Multibyte (utf8mb4) character encoding.
|
||||
*
|
||||
* @return boolean True if the database engine supports UTF-8 Multibyte.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public function hasUtf8mb4Support();
|
||||
}
|
||||
Reference in New Issue
Block a user