Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/Build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:

- name: Run python tests
run: docker exec kphp-build-container-${{matrix.os}} bash -c
"chown -R kitten /home && su - kitten -c 'GITHUB_ACTIONS=1 KPHP_CXX=${{matrix.compiler}} python3 -m pytest --tb=native -n$(nproc) $GITHUB_WORKSPACE/tests/python/'"
"chown -R kitten /home && su kitten -c 'GITHUB_ACTIONS=1 KPHP_CXX=${{matrix.compiler}} python3 -m pytest --tb=native -n$(nproc) $GITHUB_WORKSPACE/tests/python/'"

- name: Remove docker container
run: docker rm -f kphp-build-container-${{matrix.os}}
Expand All @@ -95,7 +95,7 @@ jobs:

- name: Setup Environment
run: |
brew install re2c cmake coreutils glib-openssl libiconv re2 fmt h3 yaml-cpp msgpack-cxx zstd googletest php@7.4
brew install re2c cmake coreutils glib-openssl libiconv re2 fmt h3 yaml-cpp mysql msgpack-cxx zstd googletest php@7.4
brew link --overwrite php@7.4
pip3 install jsonschema
rm -rf /usr/local/opt/openssl
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/Dockerfile.buster
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@ FROM debian:buster
ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && \
apt-get install -y --no-install-recommends apt-utils ca-certificates gnupg wget && \
apt-get install -y --no-install-recommends apt-utils ca-certificates gnupg wget lsb-release && \
echo "deb https://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list && \
wget -qO - https://repo.vkpartner.ru/GPG-KEY.pub | apt-key add - && \
echo "deb https://repo.vkpartner.ru/kphp-buster/ buster main" >> /etc/apt/sources.list && \
wget -qO - https://packages.sury.org/php/apt.gpg | apt-key add - && \
echo "deb https://packages.sury.org/php/ buster main" >> /etc/apt/sources.list.d/php.list && \
TEMP_DEB="$(mktemp)" && \
wget -O "$TEMP_DEB" 'https://dev.mysql.com/get/mysql-apt-config_0.8.22-1_all.deb' && \
dpkg -i "$TEMP_DEB" && \
rm -f "$TEMP_DEB" && \
apt-get update && \
apt-get install -y --no-install-recommends \
git cmake-data=3.18* cmake=3.18* make g++ gperf netcat \
python3-minimal python3-dev libpython3-dev python3-jsonschema python3-setuptools python3-pip \
curl-kphp-vk kphp-timelib libuber-h3-dev libfmt-dev libgtest-dev libgmock-dev libre2-dev libpcre3-dev \
libzstd-dev libyaml-cpp-dev libmsgpack-dev libnghttp2-dev zlib1g-dev php7.4-dev && \
pip3 install wheel portalocker psutil requests-toolbelt pytest pytest-xdist zstandard && \
libzstd-dev libyaml-cpp-dev libmsgpack-dev libnghttp2-dev zlib1g-dev php7.4-dev mysql-server libmysqlclient-dev && \
pip3 install wheel portalocker psutil requests-toolbelt pytest pytest-xdist pytest-mysql zstandard && \
rm -rf /var/lib/apt/lists/*

RUN useradd -ms /bin/bash kitten
4 changes: 2 additions & 2 deletions .github/workflows/Dockerfile.focal
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ RUN apt-get update && \
git cmake make clang g++ g++-10 gperf netcat \
python3-minimal python3-dev libpython3-dev python3-jsonschema python3-setuptools python3-pip \
curl-kphp-vk kphp-timelib libuber-h3-dev libfmt-dev libgtest-dev libgmock-dev libre2-dev libpcre3-dev \
libzstd-dev libyaml-cpp-dev libmsgpack-dev libnghttp2-dev zlib1g-dev php7.4-dev && \
pip3 install wheel portalocker psutil requests-toolbelt pytest pytest-xdist zstandard && \
libzstd-dev libyaml-cpp-dev libmsgpack-dev libnghttp2-dev zlib1g-dev php7.4-dev mysql-server libmysqlclient-dev && \
pip3 install wheel portalocker psutil requests-toolbelt pytest pytest-xdist pytest-mysql zstandard && \
rm -rf /var/lib/apt/lists/*

RUN useradd -ms /bin/bash kitten
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ install(FILES ${AUTO_DIR}/runtime/runtime-headers.h
DESTINATION ${INSTALL_KPHP_SOURCE}/objs/generated/auto/runtime/)

set(CPACK_DEBIAN_KPHP_PACKAGE_DEPENDS "vk-flex-data, curl-kphp-vk, libuber-h3, libpcre3-dev, libre2-dev, libyaml-cpp-dev, libssl-dev, zlib1g-dev, \
libzstd-dev, g++, libnghttp2-dev, libmsgpack-dev, kphp-timelib")
libzstd-dev, g++, libnghttp2-dev, libmsgpack-dev, kphp-timelib, libmysqlclient-dev")
set(CPACK_DEBIAN_KPHP_PACKAGE_RECOMMENDS "php7.4-vkext, vk-tl-tools")
set(CPACK_DEBIAN_KPHP_DESCRIPTION "kphp2cpp compiler and runtime for it")
set(CPACK_DEBIAN_KPHP_PACKAGE_NAME "kphp")
Expand Down
2 changes: 2 additions & 0 deletions builtin-functions/_functions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ if (0) {
require_once __DIR__ . '/uberh3.txt';
require_once __DIR__ . '/spl.txt';
require_once __DIR__ . '/ffi.txt';
require_once __DIR__ . '/pdo/PDO.php';
require_once __DIR__ . '/pdo/PDOStatement.php';

interface Throwable {
public function getMessage () ::: string;
Expand Down
42 changes: 42 additions & 0 deletions builtin-functions/pdo/PDO.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

require_once __DIR__ . '/PDOStatement.php';

class PDO {
/**
* Sets the timeout value in seconds for communications with the database.
* @link https://php.net/manual/en/pdo.constants.php#pdo.constants.attr-timeout
*/
const ATTR_TIMEOUT = 2;

public function __construct(
string $dsn,
?string $username = null,
?string $password = null,
?array $options = null
): PDO;

/** @kphp-extern-func-info resumable */
public function query(string $query): ?PDOStatement; // TODO: $fetchMode is not supported

/** @kphp-extern-func-info resumable */
public function exec(string $statement): int|false;

public function errorCode(): ?string;
public function errorInfo(): (int|string)[];

// These methods are not supported yet:
//
// public function prepare(string $query, array $options = []): ?PDOStatement;
// public function beginTransaction(): bool;
// public function commit(): bool;

// public function getAttribute(int $attribute): bool|int|string|array|null;
// public function inTransaction(): bool;
// public function lastInsertId(?string $name = null): string|false;
// public static function getAvailableDrivers(): array;
// public function quote(string $string, int $type = PDO::PARAM_STR): string|false;
// public function rollBack(): bool;
// public function setAttribute(int $attribute, mixed $value): bool;
}

46 changes: 46 additions & 0 deletions builtin-functions/pdo/PDOStatement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

require_once __DIR__ . '/PDO.php';

class PDOStatement {
/**
* @kphp-const
*/
public string $queryString;

public function fetch(): mixed; // TODO: only default behaviour supported
public function fetchAll(): mixed[]; // TODO: only default behaviour supported

// These methods are not supported yet:
//
// public function execute(?array $params = null): bool;
// public bindColumn(
// string|int $column,
// mixed &$var,
// int $type = PDO::PARAM_STR,
// int $maxLength = 0,
// mixed $driverOptions = null
// ): bool
// public bindParam(
// string|int $param,
// mixed &$var,
// int $type = PDO::PARAM_STR,
// int $maxLength = 0,
// mixed $driverOptions = null
// ): bool
// public bindValue(string|int $param, mixed $value, int $type = PDO::PARAM_STR): bool
// public closeCursor(): bool
// public columnCount(): int
// public debugDumpParams(): ?bool
// public errorCode(): ?string
// public errorInfo(): array
// public fetchAll(int $mode = PDO::FETCH_DEFAULT): array
// public fetchColumn(int $column = 0): mixed
// public fetchObject(?string $class = "stdClass", array $constructorArgs = []): object|false
// public getAttribute(int $name): mixed
// public getColumnMeta(int $column): array|false
// public nextRowset(): bool
// public rowCount(): int
// public setAttribute(int $attribute, mixed $value): bool
// public setFetchMode(int $mode): bool
}
3 changes: 2 additions & 1 deletion compiler/code-gen/files/type-tagger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ std::map<int, std::string> TypeTagger::collect_hash_of_types() const noexcept {
"array< array< mixed > >",
"class_instance<C$KphpJobWorkerResponse>",
"class_instance<C$VK$TL$RpcResponse>",
"array< class_instance<C$VK$TL$RpcResponse> >"
"array< class_instance<C$VK$TL$RpcResponse> >",
"class_instance<C$PDOStatement>",
};

for (const auto *type : forkable_types_) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/compiler-settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ void CompilerSettings::init() {
ld_flags.value_ = extra_ld_flags.get();
append_curl(cxx_default_flags, ld_flags.value_);
append_apple_options(cxx_default_flags, ld_flags.value_);
std::vector<vk::string_view> external_static_libs{"pcre", "re2", "yaml-cpp", "h3", "ssl", "z", "zstd", "nghttp2", "kphp-timelib"};
std::vector<vk::string_view> external_static_libs{"pcre", "re2", "yaml-cpp", "h3", "ssl", "z", "zstd", "nghttp2", "kphp-timelib", "mysqlclient"};

#ifdef KPHP_TIMELIB_LIB_DIR
ld_flags.value_ += " -L" KPHP_TIMELIB_LIB_DIR;
Expand All @@ -326,7 +326,7 @@ void CompilerSettings::init() {
ld_flags.value_ += " /opt/homebrew/lib/libucontext.a";
#endif

std::vector<vk::string_view> external_libs{"pthread", "crypto", "m"};
std::vector<vk::string_view> external_libs{"pthread", "crypto", "m", "dl"};
#if defined(__APPLE__)
append_if_doesnt_contain(ld_flags.value_, external_static_libs, "-l");
auto flex_prefix = kphp_src_path.value_ + "objs/flex/lib";
Expand Down
1 change: 1 addition & 0 deletions docs/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ url_github_kphp_snippets: https://github.com/VKCOM/kphp-snippets
url_github_kphp_tools: https://github.com/VKCOM/kphp-tools
url_github_issues: https://github.com/VKCOM/kphp/issues
url_functions_txt: https://github.com/VKCOM/kphp/blob/master/builtin-functions/_functions.txt
url_PDO: https://github.com/VKCOM/kphp/blob/master/builtin-functions/PDO/PDO.php
url_dockerfile: https://github.com/VKCOM/kphp/blob/master/Dockerfile
url_license_file: https://github.com/VKCOM/kphp/blob/master/LICENSE
url_vertex_desc_json: https://github.com/VKCOM/kphp/blob/master/compiler/vertex-desc.json
Expand Down
40 changes: 35 additions & 5 deletions docs/kphp-client/working-with-external-db/invoking-mysql.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,45 @@ sort: 2
---

# Invoking MySQL
Basic [PDO](https://www.php.net/manual/en/book.pdo.php) interface is supported for communication with MySQL databases.
You can see the actual interface [here]({{site.url_PDO}}).

With it you can execute simple text SQL queries:
```PHP
function sample(string $mysql_host, int $mysql_port, string $dbname, string $user, string $password) {
// Create the connection:
$db = new PDO(
"mysql:host=$mysql_host;port=$mysql_port;dbname=$dbname",
$user,
$password,
[PDO::ATTR_TIMEOUT => 2] // Only PDO::ATTR_TIMEOUT option is supported
);

// Send simple SELECT like text query:
$stmt = $db->query("SELECT * FROM SomeTable");
if ($db->errorCode() == 0) { // Simple error handling
var_dump($db->errorInfo());
return;
}
$res = $stmt->fetchAll();
var_dump($res);

// Send simple modify text query:
$affected_rows = $db->exec("DELETE FROM SomeTable WHERE id=42");
var_dump($affected_rows);
}

```danger
:(
```
> **Note:** Only default behaviour is supported for exposed methods.
>
> Particularly, it means that features like _Prepared statements_, _Unbuffered fetching mode_ are not supported so far.

KPHP implements some *mysqli_…()* functions, that can be called MySQL support somehow.
> **Note:** But the advantage of this PDO::MySQL version is asynchronicity. The main communication methods like `PDO::query` and `PDO::exec` are marked as _resumable_ functions.
>
> It means that these method calls will be considered as suspendable points by other resumable functions (a.k.a. coroutines).
----
Also KPHP implements some *mysqli_…()* functions, that can be called MySQL support somehow.

But, at VK.com, we use a special *db-proxy* layer between KPHP and MySQL databases. It is a daemon running on every server: it manages connections, performs master-replica routing, handles access rights.

As a result, KPHP just skips credentials passed to *mysqli_connect()*. Moreover, MySQL connection can only be opened to *localhost* with unix socket.

So, MySQL support for "real-world usage" is also still to be done.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Add external repositories
```bash
apt-get update
# utils for adding repositories
apt-get install -y --no-install-recommends apt-utils ca-certificates gnupg wget
apt-get install -y --no-install-recommends apt-utils ca-certificates gnupg wget lsb-release
# for newest cmake package
echo "deb https://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list
# for curl-kphp-vk, libuber-h3-dev packages and kphp-timelib
Expand All @@ -40,13 +40,18 @@ echo "deb https://repo.vkpartner.ru/kphp-buster/ buster main" >> /etc/apt/source
# for php7.4-dev package
wget -qO - https://packages.sury.org/php/apt.gpg | apt-key add -
echo "deb https://packages.sury.org/php/ buster main" >> /etc/apt/sources.list.d/php.list
# for libmysqlclient-dev
TEMP_DEB="$(mktemp)"
wget -O "$TEMP_DEB" 'https://dev.mysql.com/get/mysql-apt-config_0.8.20-1_all.deb'
DEBIAN_FRONTEND=noninteractive dpkg -i "$TEMP_DEB"
rm -f "$TEMP_DEB"
```
Install packages
```bash
apt-get update
apt install git cmake-data=3.16* cmake=3.16* make g++ gperf python3-minimal python3-jsonschema \
curl-kphp-vk libuber-h3-dev kphp-timelib libfmt-dev libgtest-dev libgmock-dev libre2-dev libpcre3-dev \
libzstd-dev libyaml-cpp-dev libmsgpack-dev libnghttp2-dev zlib1g-dev php7.4-dev
libzstd-dev libyaml-cpp-dev libmsgpack-dev libnghttp2-dev zlib1g-dev php7.4-dev libmysqlclient-dev
```


Expand All @@ -65,14 +70,14 @@ Install packages
apt-get update
apt install git cmake make g++ gperf python3-minimal python3-jsonschema \
curl-kphp-vk libuber-h3-dev kphp-timelib libfmt-dev libgtest-dev libgmock-dev libre2-dev libpcre3-dev \
libzstd-dev libyaml-cpp-dev libmsgpack-dev libnghttp2-dev zlib1g-dev php7.4-dev
libzstd-dev libyaml-cpp-dev libmsgpack-dev libnghttp2-dev zlib1g-dev php7.4-dev libmysqlclient-dev
```


##### MacOS with Intel chipset
Make sure you have `brew` and `clang` (at least `Apple clang version 10.0.0`)
```bash
brew install re2c cmake coreutils glib-openssl libiconv re2 fmt h3 yaml-cpp msgpack-cxx zstd googletest php@7.4
brew install re2c cmake coreutils glib-openssl libiconv re2 fmt h3 yaml-cpp mysql msgpack-cxx zstd googletest php@7.4
brew link --overwrite php@7.4
pip3 install jsonschema
```
Expand Down
2 changes: 1 addition & 1 deletion net/net-mysql-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ static int sqlc_inner_authorise (struct connection *c) {
size_t expected_length = sizeof (struct mysql_auth_packet_end);
if (((struct mysql_auth_packet_end*)p)->proto_len){
if (strncmp(((struct mysql_auth_packet_end*)p)->proto, "mysql_native_password", 21)){
kprintf("unknown auth_proto %s\n", ((struct mysql_auth_packet_end*)p)->proto);
vkprintf(1, "unknown auth_proto %s\n", ((struct mysql_auth_packet_end*)p)->proto);
return -1;
}
expected_length += 22;
Expand Down
2 changes: 1 addition & 1 deletion net/net-reactor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ int net_reactor_runqueue(net_reactor_ctx_t *ctx) {
ev->timestamp = ctx->timestamp;
net_reactor_put_event_into_heap(ctx, ev);
} else if (res > 0) {
net_reactor_insert(ctx, fd, res & 0xf);
net_reactor_insert(ctx, fd, res & (EVT_LEVEL | EVT_RWX));
} else if (res == EVA_CONTINUE) {
ev->ready = 0;
}
Expand Down
5 changes: 5 additions & 0 deletions runtime/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "runtime/net_events.h"
#include "runtime/on_kphp_warning_callback.h"
#include "runtime/openssl.h"
#include "runtime/pdo/pdo.h"
#include "runtime/profiler.h"
#include "runtime/regexp.h"
#include "runtime/resumable.h"
Expand All @@ -47,12 +48,14 @@
#include "runtime/url.h"
#include "runtime/zlib.h"
#include "runtime/timelib_wrapper.h"
#include "server/database-drivers/adaptor.h"
#include "server/job-workers/job-message.h"
#include "server/json-logger.h"
#include "server/php-engine-vars.h"
#include "server/php-queries.h"
#include "server/php-query-data.h"
#include "server/workers-control.h"
#include "server/database-drivers/mysql/mysql.h"

static enum {
QUERY_TYPE_NONE,
Expand Down Expand Up @@ -2234,6 +2237,8 @@ static void free_runtime_libs() {
free_migration_php8();

vk::singleton<JsonLogger>::get().reset_buffers();
database_drivers::free_mysql_lib();
vk::singleton<database_drivers::Adaptor>::get().reset();
free_interface_lib();
}

Expand Down
8 changes: 7 additions & 1 deletion runtime/net_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "runtime/allocator.h"
#include "runtime/job-workers/job-interface.h"
#include "runtime/rpc.h"
#include "server/database-drivers/adaptor.h"
#include "server/database-drivers/response.h"
#include "server/php-queries.h"

int timeout_convert_to_ms(double timeout) {
Expand All @@ -35,7 +37,7 @@ double get_precise_now() {
return kphp_precise_now;
}

static bool process_net_event(net_event_t *e) {
bool process_net_event(net_event_t *e) {
if (e == nullptr) {
return false;
}
Expand All @@ -50,6 +52,10 @@ static bool process_net_event(net_event_t *e) {
[&](const net_events_data::job_worker_answer &data) {
process_job_answer(e->slot_id, data.job_result);
},
[&](database_drivers::Response *response) {
php_assert(e->slot_id == response->bound_request_id);
vk::singleton<database_drivers::Adaptor>::get().process_external_db_response_event(std::unique_ptr<database_drivers::Response>(response));
},
}, e->data);

return true;
Expand Down
15 changes: 15 additions & 0 deletions runtime/pdo/abstract_pdo_driver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Compiler for PHP (aka KPHP)
// Copyright (c) 2021 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#include "runtime/pdo/abstract_pdo_driver.h"

#include "server/database-drivers/adaptor.h"

namespace pdo {

AbstractPdoDriver::~AbstractPdoDriver() noexcept {
vk::singleton<database_drivers::Adaptor>::get().remove_connector(connector_id);
}

} // namespace pdo
Loading