This commit is contained in:
2025-10-13 09:04:00 +00:00
parent 7a3b2960f8
commit 4ee3212899
230 changed files with 40880 additions and 245 deletions
+22
View File
@@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
+4
View File
@@ -0,0 +1,4 @@
# These are supported funding model platforms
open_collective: medoo
custom: ["https://paypal.me/AngelaonLai"]
@@ -0,0 +1,26 @@
---
name: Bug report
about: Create a report to help us improve
---
**Information**
- **Version of Medoo:** [Enter the version number]
- **Version of PHP:** [Enter the version number]
- **Type of Database:** [MySQL, MSSQL, SQLite, etc.]
- **System:** [Linux|Windows|Mac]
**Describe the Problem**
A clear and concise description of what the problem is.
**Code Snippet**
The detail code you are using that causes the problem:
```php
// Write your PHP code here
```
**Expected Behavior**
A clear and concise description of what you expected to happen.
**Actual Behavior**
A clear and concise description of what actually happened.
+39
View File
@@ -0,0 +1,39 @@
name: build
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
php: ['7.3', '7.4', '8.2', '8.3']
steps:
- uses: actions/checkout@v3.3.0
- name: Validate composer.json and composer.lock
run: composer validate --strict
- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v3.2.2
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: Run test suite
run: composer run-script test
+225
View File
@@ -0,0 +1,225 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
*.publishproj
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#############
## Windows detritus
#############
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store
#############
## Python
#############
*.py[cod]
# Packages
*.egg
*.egg-info
dist/
build/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
#php-cs-fixer
/.php_cs
#PHPUnit
/.phpunit.cache
/composer.lock
/vendor
+18
View File
@@ -0,0 +1,18 @@
<?php
$config = new PhpCsFixer\Config();
$config
->setRules([
'@PSR2' => true,
'@PSR12' => true,
'array_syntax' => ['syntax' => 'short'],
'nullable_type_declaration_for_default_null_value' => true
])
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
)
;
return $config;
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Angel Lai
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+120
View File
@@ -0,0 +1,120 @@
<p align="center">
<a href="https://medoo.in" target="_blank"><img src="https://cloud.githubusercontent.com/assets/1467904/19835326/ca62bc36-9ebd-11e6-8b37-7240d76319cd.png"></a>
</p>
<p align="center">
<a href="https://github.com/catfan/Medoo/actions"><img alt="Build Status" src="https://github.com/catfan/Medoo/actions/workflows/php.yml/badge.svg"></a>
<a href="https://packagist.org/packages/catfan/medoo"><img alt="Total Downloads" src="https://poser.pugx.org/catfan/medoo/downloads"></a>
<a href="https://packagist.org/packages/catfan/medoo"><img alt="Latest Stable Version" src="https://poser.pugx.org/catfan/medoo/v/stable"></a>
<a href="https://packagist.org/packages/catfan/medoo"><img alt="License" src="https://poser.pugx.org/catfan/medoo/license"></a>
<a href="https://opencollective.com/medoo"><img alt="Backers on Open Collective" src="https://opencollective.com/Medoo/backers/badge.svg"></a>
<a href="https://opencollective.com/medoo"><img alt="Sponsors on Open Collective" src="https://opencollective.com/Medoo/sponsors/badge.svg"> </a>
</p>
> The lightweight PHP database framework to accelerate development.
## Features
* **Lightweight** - Single-file framework with minimal dependencies.
* **Easy** - Simple and intuitive API for quick integration.
* **Powerful** - Supports complex SQL queries, data mapping, and SQL injection prevention.
* **Compatible** - Works with MySQL, MariaDB, PostgreSQL, SQLite, MSSQL, Oracle, Sybase, and more.
* **Friendly** - Integrates seamlessly with Laravel, CodeIgniter, Yii, Slim, and other PHP frameworks.
* **Free** - Licensed under MIT, free to use for any purpose.
## Requirements
- PHP 7.3 or later
- PDO extension enabled
## Get Started
### Install via composer
Add Medoo to the `composer.json` configuration file.
```bash
$ composer require catfan/medoo
```
Then update Composer
```bash
$ composer update
```
```php
// Require Composer's autoloader
require 'vendor/autoload.php';
// Import Medoo namespace
use Medoo\Medoo;
// Initialize database connection
$database = new Medoo([
'type' => 'mysql',
'host' => 'localhost',
'database' => 'name',
'username' => 'your_username',
'password' => 'your_password'
]);
// Insert data
$database->insert('account', [
'user_name' => 'foo',
'email' => 'foo@bar.com'
]);
// Retrieve data
$data = $database->select('account', [
'user_name',
'email'
], [
'user_id' => 50
]);
echo json_encode($data);
// [{
// "user_name" : "foo",
// "email" : "foo@bar.com",
// }]
```
## Contribution Guidelines
Before submitting a pull request, ensure compatibility with multiple database engines and include unit tests when possible.
### Testing & Code Style
- Run `phpunit tests` to execute unit tests.
- Use `php-cs-fixer fix` to enforce code style consistency.
### Commit Message Format
Each commit should begin with a tag indicating the type of change:
- `[fix]` for bug fixes
- `[feature]` for new features
- `[update]` for improvements
Keep contributions simple and well-documented.
## License
Medoo is released under the MIT License.
## Links
* Official website: [https://medoo.in](https://medoo.in)
* Documentation: [https://medoo.in/doc](https://medoo.in/doc)
* Twitter: [https://twitter.com/MedooPHP](https://twitter.com/MedooPHP)
* Open Collective: [https://opencollective.com/medoo](https://opencollective.com/medoo)
## Support Our Other Product
[Gear Browser - Web Browser for Geek](https://gear4.app)
[![Gear Browser](https://github.com/catfan/Medoo/assets/1467904/bc5059d4-6a2d-4bbf-90d9-a9f71bae3335)](https://gear4.app)
+43
View File
@@ -0,0 +1,43 @@
{
"name": "catfan/medoo",
"type": "framework",
"description": "The lightweight PHP database framework to accelerate development",
"keywords": ["database", "database library", "lightweight", "PHP framework", "SQL", "MySQL", "MSSQL", "SQLite", "PostgreSQL", "MariaDB", "Oracle"],
"homepage": "https://medoo.in",
"license": "MIT",
"support": {
"issues": "https://github.com/catfan/Medoo/issues",
"source": "https://github.com/catfan/Medoo"
},
"authors": [
{"name": "Angel Lai", "email": "angel@medoo.in"}
],
"require": {
"php": ">=7.3",
"ext-pdo": "*"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"suggest": {
"ext-pdo_mysql": "For MySQL or MariaDB database",
"ext-pdo_sqlsrv": "For MSSQL database on both Window/Liunx platform",
"ext-pdo_dblib": "For MSSQL or Sybase database on Linux/UNIX platform",
"ext-pdo_oci": "For Oracle database",
"ext-pdo_pqsql": "For PostgreSQL database",
"ext-pdo_sqlite": "For SQLite database"
},
"autoload": {
"psr-4": {
"Medoo\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Medoo\\Tests\\": "tests/"
}
},
"scripts": {
"test": "vendor/bin/phpunit tests"
}
}
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
cacheResultFile=".phpunit.cache/test-results"
executionOrder="depends,defects"
failOnRisky="true"
failOnWarning="true"
verbose="true">
<testsuites>
<testsuite name="Medoo Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<coverage cacheDirectory=".phpunit.cache/code-coverage"
processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
</phpunit>
+2310
View File
File diff suppressed because it is too large Load Diff
+117
View File
@@ -0,0 +1,117 @@
<?php
namespace Medoo\Tests;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class AggregateTest extends MedooTestCase
{
/**
* @covers ::count()
* @covers ::aggregate()
* @covers ::selectContext()
* @dataProvider typesProvider
*/
public function testCount($type)
{
$this->setType($type);
$this->database->count("account", [
"gender" => "female"
]);
$this->assertQuery(
<<<EOD
SELECT COUNT(*)
FROM "account"
WHERE "gender" = 'female'
EOD,
$this->database->queryString
);
}
/**
* @covers ::max()
* @covers ::aggregate()
* @covers ::selectContext()
* @dataProvider typesProvider
*/
public function testMax($type)
{
$this->setType($type);
$this->database->max("account", "age");
$this->assertQuery(
<<<EOD
SELECT MAX("age")
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::min()
* @covers ::aggregate()
* @covers ::selectContext()
* @dataProvider typesProvider
*/
public function testMin($type)
{
$this->setType($type);
$this->database->min("account", "age");
$this->assertQuery(
<<<EOD
SELECT MIN("age")
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::avg()
* @covers ::aggregate()
* @covers ::selectContext()
* @dataProvider typesProvider
*/
public function testAvg($type)
{
$this->setType($type);
$this->database->avg("account", "age");
$this->assertQuery(
<<<EOD
SELECT AVG("age")
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::sum()
* @covers ::aggregate()
* @covers ::selectContext()
* @dataProvider typesProvider
*/
public function testSum($type)
{
$this->setType($type);
$this->database->sum("account", "money");
$this->assertQuery(
<<<EOD
SELECT SUM("money")
FROM "account"
EOD,
$this->database->queryString
);
}
}
+142
View File
@@ -0,0 +1,142 @@
<?php
namespace Medoo\Tests;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class CreateTest extends MedooTestCase
{
/**
* @covers ::create()
* @dataProvider typesProvider
*/
public function testCreate($type)
{
$this->setType($type);
$this->database->create("account", [
"id" => [
"INT",
"NOT NULL",
"AUTO_INCREMENT"
],
"email" => [
"VARCHAR(70)",
"NOT NULL",
"UNIQUE"
],
"PRIMARY KEY (<id>)"
], [
"AUTO_INCREMENT" => 200
]);
$this->assertQuery(
[
'default' => <<<EOD
CREATE TABLE IF NOT EXISTS "account"
("id" INT NOT NULL AUTO_INCREMENT,
"email" VARCHAR(70) NOT NULL UNIQUE,
PRIMARY KEY ("id"))
AUTO_INCREMENT = 200
EOD,
'mssql' => <<<EOD
CREATE TABLE [account]
([id] INT NOT NULL AUTO_INCREMENT,
[email] VARCHAR(70) NOT NULL UNIQUE,
PRIMARY KEY ([id]))
AUTO_INCREMENT = 200
EOD,
'oracle' => <<<EOD
CREATE TABLE "account"
("id" INT NOT NULL AUTO_INCREMENT,
"email" VARCHAR(70) NOT NULL UNIQUE,
PRIMARY KEY ("id"))
AUTO_INCREMENT = 200
EOD
],
$this->database->queryString
);
}
/**
* @covers ::create()
* @dataProvider typesProvider
*/
public function testCreateWithStringDefinition($type)
{
$this->setType($type);
$this->database->create("account", [
"id" => "INT NOT NULL AUTO_INCREMENT",
"email" => "VARCHAR(70) NOT NULL UNIQUE"
]);
$this->assertQuery(
[
'default' => <<<EOD
CREATE TABLE IF NOT EXISTS "account"
("id" INT NOT NULL AUTO_INCREMENT,
"email" VARCHAR(70) NOT NULL UNIQUE)
EOD,
'mssql' => <<<EOD
CREATE TABLE [account]
([id] INT NOT NULL AUTO_INCREMENT,
[email] VARCHAR(70) NOT NULL UNIQUE)
EOD,
'oracle' => <<<EOD
CREATE TABLE "account"
("id" INT NOT NULL AUTO_INCREMENT,
"email" VARCHAR(70) NOT NULL UNIQUE)
EOD
],
$this->database->queryString
);
}
/**
* @covers ::create()
* @dataProvider typesProvider
*/
public function testCreateWithSingleOption($type)
{
$this->setType($type);
$this->database->create("account", [
"id" => [
"INT",
"NOT NULL",
"AUTO_INCREMENT"
],
"email" => [
"VARCHAR(70)",
"NOT NULL",
"UNIQUE"
]
], "TABLESPACE tablespace_name");
$this->assertQuery(
[
'default' => <<<EOD
CREATE TABLE IF NOT EXISTS "account"
("id" INT NOT NULL AUTO_INCREMENT,
"email" VARCHAR(70) NOT NULL UNIQUE)
TABLESPACE tablespace_name
EOD,
'mssql' => <<<EOD
CREATE TABLE [account]
([id] INT NOT NULL AUTO_INCREMENT,
[email] VARCHAR(70) NOT NULL UNIQUE)
TABLESPACE tablespace_name
EOD,
'oracle' => <<<EOD
CREATE TABLE "account"
("id" INT NOT NULL AUTO_INCREMENT,
"email" VARCHAR(70) NOT NULL UNIQUE)
TABLESPACE tablespace_name
EOD
],
$this->database->queryString
);
}
}
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace Medoo\Tests;
use Medoo\Medoo;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class DeleteTest extends MedooTestCase
{
/**
* @covers ::delete()
* @dataProvider typesProvider
*/
public function testDelete($type)
{
$this->setType($type);
$this->database->delete("account", [
"AND" => [
"type" => "business",
"age[<]" => 18
]
]);
$this->assertQuery(
<<<EOD
DELETE FROM "account"
WHERE ("type" = 'business' AND "age" < 18)
EOD,
$this->database->queryString
);
}
/**
* @covers ::delete()
* @dataProvider typesProvider
*/
public function testDeleteRaw($type)
{
$this->setType($type);
$whereClause = Medoo::raw("WHERE (<type> = :type AND <age> < :age)", [
':type' => 'business',
':age' => 18,
]);
$this->database->delete("account", $whereClause);
$this->assertQuery(
<<<EOD
DELETE FROM "account"
WHERE ("type" = 'business' AND "age" < 18)
EOD,
$this->database->queryString
);
}
}
+51
View File
@@ -0,0 +1,51 @@
<?php
namespace Medoo\Tests;
use Medoo\Medoo;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class DropTest extends MedooTestCase
{
/**
* @covers ::drop()
* @dataProvider typesProvider
*/
public function testDrop($type)
{
$this->setType($type);
$this->database->drop("account");
$this->assertQuery(
<<<EOD
DROP TABLE IF EXISTS "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::drop()
*/
public function testDropWithPrefix()
{
$database = new Medoo([
'testMode' => true,
'prefix' => 'PREFIX_'
]);
$database->type = "sqlite";
$database->drop("account");
$this->assertQuery(
<<<EOD
DROP TABLE IF EXISTS "PREFIX_account"
EOD,
$database->queryString
);
}
}
+163
View File
@@ -0,0 +1,163 @@
<?php
namespace Medoo\Tests;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class GetTest extends MedooTestCase
{
/**
* @covers ::get()
* @dataProvider typesProvider
*/
public function testGet($type)
{
$this->setType($type);
$this->database->get("account", "email", [
"user_id" => 1234
]);
$this->assertQuery([
'default' => <<<EOD
SELECT "email"
FROM "account"
WHERE "user_id" = 1234
LIMIT 1
EOD,
'mssql' => <<<EOD
SELECT [email]
FROM [account]
WHERE [user_id] = 1234
ORDER BY (SELECT 0)
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
EOD,
'oracle' => <<<EOD
SELECT "email"
FROM "account"
WHERE "user_id" = 1234
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
EOD,
], $this->database->queryString);
}
/**
* @covers ::get()
* @dataProvider typesProvider
*/
public function testGetWithColumns($type)
{
$this->setType($type);
$this->database->get("account", [
"email",
"location"
], [
"user_id" => 1234
]);
$this->assertQuery([
'default' => <<<EOD
SELECT "email","location"
FROM "account"
WHERE "user_id" = 1234
LIMIT 1
EOD,
'mssql' => <<<EOD
SELECT [email],[location]
FROM [account]
WHERE [user_id] = 1234
ORDER BY (SELECT 0)
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
EOD,
'oracle' => <<<EOD
SELECT "email","location"
FROM "account"
WHERE "user_id" = 1234
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
EOD,
], $this->database->queryString);
}
/**
* @covers ::get()
* @dataProvider typesProvider
*/
public function testGetWithJoin($type)
{
$this->setType($type);
$this->database->get("post", [
"[>]account" => "user_id"
], [
"post.content",
"account.user_name"
]);
$this->assertQuery([
'default' => <<<EOD
SELECT "post"."content","account"."user_name"
FROM "post"
LEFT JOIN "account" USING ("user_id")
LIMIT 1
EOD,
'mssql' => <<<EOD
SELECT [post].[content],[account].[user_name]
FROM [post]
LEFT JOIN [account] USING ([user_id])
ORDER BY (SELECT 0)
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
EOD,
'oracle' => <<<EOD
SELECT "post"."content","account"."user_name"
FROM "post"
LEFT JOIN "account" USING ("user_id")
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
EOD,
], $this->database->queryString);
}
/**
* @covers ::get()
* @dataProvider typesProvider
*/
public function testGetWithJoinAndWhere($type)
{
$this->setType($type);
$this->database->get("post", [
"[>]account" => "user_id"
], [
"post.content",
"account.user_name"
], [
'account.age[>]' => 18
]);
$this->assertQuery([
'default' => <<<EOD
SELECT "post"."content","account"."user_name"
FROM "post"
LEFT JOIN "account" USING ("user_id")
WHERE "account"."age" > 18
LIMIT 1
EOD,
'mssql' => <<<EOD
SELECT [post].[content],[account].[user_name]
FROM [post]
LEFT JOIN [account] USING ([user_id])
WHERE [account].[age] > 18
ORDER BY (SELECT 0)
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
EOD,
'oracle' => <<<EOD
SELECT "post"."content","account"."user_name"
FROM "post"
LEFT JOIN "account" USING ("user_id")
WHERE "account"."age" > 18
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
EOD,
], $this->database->queryString);
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace Medoo\Tests;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class HasTest extends MedooTestCase
{
/**
* @covers ::has()
* @covers ::selectContext()
* @dataProvider typesProvider
*/
public function testHas($type)
{
$this->setType($type);
$this->database->has("account", [
"user_name" => "foo"
]);
$this->assertQuery([
'default' => <<<EOD
SELECT EXISTS(SELECT 1 FROM "account" WHERE "user_name" = 'foo')
EOD,
'mssql' => <<<EOD
SELECT TOP 1 1 FROM [account] WHERE [user_name] = 'foo'
EOD
], $this->database->queryString);
}
}
+242
View File
@@ -0,0 +1,242 @@
<?php
namespace Medoo\Tests;
use Medoo\Medoo;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class InsertTest extends MedooTestCase
{
/**
* @covers ::insert()
* @covers ::typeMap()
* @dataProvider typesProvider
*/
public function testInsert($type)
{
$this->setType($type);
$this->database->insert("account", [
"user_name" => "foo",
"email" => "foo@bar.com"
]);
$this->assertQuery(
<<<EOD
INSERT INTO "account" ("user_name", "email")
VALUES ('foo', 'foo@bar.com')
EOD,
$this->database->queryString
);
}
/**
* @covers ::insert()
* @covers ::typeMap()
* @dataProvider typesProvider
*/
public function testInsertWithArray($type)
{
$this->setType($type);
$this->database->insert("account", [
"user_name" => "foo",
"lang" => ["en", "fr"]
]);
$this->assertQuery([
'default' => <<<EOD
INSERT INTO "account" ("user_name", "lang")
VALUES ('foo', 'a:2:{i:0;s:2:"en";i:1;s:2:"fr";}')
EOD,
'mysql' => <<<EOD
INSERT INTO "account" ("user_name", "lang")
VALUES ('foo', 'a:2:{i:0;s:2:\"en\";i:1;s:2:\"fr\";}')
EOD
], $this->database->queryString);
}
/**
* @covers ::insert()
* @covers ::typeMap()
* @dataProvider typesProvider
*/
public function testInsertWithJSON($type)
{
$this->setType($type);
$this->database->insert("account", [
"user_name" => "foo",
"lang [JSON]" => ["en", "fr"]
]);
$this->assertQuery([
'default' => <<<EOD
INSERT INTO "account" ("user_name", "lang")
VALUES ('foo', '["en","fr"]')
EOD,
'mysql' => <<<EOD
INSERT INTO `account` (`user_name`, `lang`)
VALUES ('foo', '[\"en\",\"fr\"]')
EOD
], $this->database->queryString);
}
/**
* @covers ::insert()
* @dataProvider typesProvider
*/
public function testInsertWithRaw($type)
{
$this->setType($type);
$this->database->insert("account", [
"user_name" => Medoo::raw("UUID()")
]);
$this->assertQuery(
<<<EOD
INSERT INTO "account" ("user_name")
VALUES (UUID())
EOD,
$this->database->queryString
);
}
/**
* @covers ::insert()
* @covers ::typeMap()
* @dataProvider typesProvider
*/
public function testInsertWithNull($type)
{
$this->setType($type);
$this->database->insert("account", [
"location" => null
]);
$this->assertQuery(
<<<EOD
INSERT INTO "account" ("location")
VALUES (NULL)
EOD,
$this->database->queryString
);
}
/**
* @covers ::insert()
* @covers ::typeMap()
* @dataProvider typesProvider
*/
public function testInsertWithObject($type)
{
$this->setType($type);
$objectData = new Foo();
$this->database->insert("account", [
"object" => $objectData
]);
$this->assertQuery(
<<<EOD
INSERT INTO "account" ("object")
VALUES (:MeD0_mK)
EOD,
$this->database->queryString
);
}
/**
* @covers ::insert()
* @dataProvider typesProvider
*/
public function testMultiInsert($type)
{
$this->setType($type);
$this->database->insert("account", [
[
"user_name" => "foo",
"email" => "foo@bar.com"
],
[
"user_name" => "bar",
"email" => "bar@foo.com"
]
]);
$this->assertQuery(
<<<EOD
INSERT INTO "account" ("user_name", "email")
VALUES ('foo', 'foo@bar.com'), ('bar', 'bar@foo.com')
EOD,
$this->database->queryString
);
}
public function testOracleWithPrimaryKeyInsert()
{
$this->setType("oracle");
$this->database->insert("ACCOUNT", [
"NAME" => "foo",
"EMAIL" => "foo@bar.com"
], "ID");
$this->assertQuery(
<<<EOD
INSERT INTO "ACCOUNT" ("NAME", "EMAIL")
VALUES ('foo', 'foo@bar.com')
RETURNING "ID" INTO :RETURNID
EOD,
$this->database->queryString
);
}
public function testOracleWithLOBsInsert()
{
$this->setType("oracle");
$fp = fopen('README.md', 'r');
$this->database->insert("ACCOUNT", [
"NAME" => "foo",
"DATA" => $fp
]);
$this->assertQuery(
<<<EOD
INSERT INTO "ACCOUNT" ("NAME", "DATA")
VALUES ('foo', EMPTY_BLOB())
RETURNING "DATA" INTO :MeD1_mK
EOD,
$this->database->queryString
);
}
public function testOracleWithLOBsAndIdInsert()
{
$this->setType("oracle");
$fp = fopen('README.md', 'r');
$this->database->insert("ACCOUNT", [
"NAME" => "foo",
"DATA" => $fp
], "ID");
$this->assertQuery(
<<<EOD
INSERT INTO "ACCOUNT" ("NAME", "DATA")
VALUES ('foo', EMPTY_BLOB())
RETURNING "DATA", "ID" INTO :MeD1_mK, :RETURNID
EOD,
$this->database->queryString
);
}
}
+82
View File
@@ -0,0 +1,82 @@
<?php
namespace Medoo\Tests;
use Medoo\Medoo;
use PHPUnit\Framework\TestCase;
class MedooTestCase extends TestCase
{
protected $database;
public $tableAliasConnector = ' AS ';
public $quotePattern = '"$1"';
public function setUp(): void
{
$this->database = new Medoo([
'testMode' => true
]);
}
public function typesProvider(): array
{
return [
'MySQL' => ['mysql'],
'MSSQL' => ['mssql'],
'SQLite' => ['sqlite'],
'PostgreSQL' => ['pgsql'],
'Oracle' => ['oracle']
];
}
public function setType($type): void
{
$this->database->setupType($type);
if ($type === 'oracle') {
$this->tableAliasConnector = ' ';
} elseif ($type === 'mysql') {
$this->quotePattern = '`$1`';
} elseif ($type === 'mssql') {
$this->quotePattern = '[$1]';
}
}
public function expectedQuery($expected): string
{
$result = preg_replace(
'/(?!\'[^\s]+\s?)"([\p{L}_][\p{L}\p{N}@$#\-_]*)"(?!\s?[^\s]+\')/u',
$this->quotePattern,
str_replace("\n", " ", $expected)
);
return str_replace(
' @AS ',
$this->tableAliasConnector,
$result
);
}
public function assertQuery($expected, $query): void
{
if (is_array($expected)) {
$this->assertEquals(
$this->expectedQuery($expected[$this->database->type] ?? $expected['default']),
$query
);
} else {
$this->assertEquals($this->expectedQuery($expected), $query);
}
}
}
class Foo
{
public $bar = "cat";
public function __wakeup()
{
$this->bar = "dog";
}
}
+152
View File
@@ -0,0 +1,152 @@
<?php
namespace Medoo\Tests;
use Medoo\Medoo;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class QueryTest extends MedooTestCase
{
/**
* @covers ::query()
* @covers ::isRaw()
* @covers ::buildRaw()
* @dataProvider typesProvider
*/
public function testQuery($type)
{
$this->setType($type);
$this->database->query("SELECT <account.email>,<account.nickname> FROM <account> WHERE <id> != 100");
$this->assertQuery(
<<<EOD
SELECT "account"."email","account"."nickname"
FROM "account"
WHERE "id" != 100
EOD,
$this->database->queryString
);
}
/**
* @covers ::query()
* @covers ::isRaw()
* @covers ::buildRaw()
*/
public function testQueryWithPrefix()
{
$database = new Medoo([
'testMode' => true,
'prefix' => 'PREFIX_'
]);
$database->query("SELECT <account.name> FROM <account>");
$this->assertQuery(
<<<EOD
SELECT "PREFIX_account"."name"
FROM "PREFIX_account"
EOD,
$database->queryString
);
}
/**
* @covers ::query()
* @covers ::isRaw()
* @covers ::buildRaw()
*/
public function testQueryTableWithPrefix()
{
$database = new Medoo([
'testMode' => true,
'prefix' => 'PREFIX_'
]);
$database->query("DROP TABLE IF EXISTS <account>");
$this->assertQuery(
<<<EOD
DROP TABLE IF EXISTS "PREFIX_account"
EOD,
$database->queryString
);
}
/**
* @covers ::query()
* @covers ::isRaw()
* @covers ::buildRaw()
*/
public function testQueryShowTableWithPrefix()
{
$database = new Medoo([
'testMode' => true,
'prefix' => 'PREFIX_'
]);
$database->query("SHOW TABLES LIKE <account>");
$this->assertQuery(
<<<EOD
SHOW TABLES LIKE "PREFIX_account"
EOD,
$database->queryString
);
}
/**
* @covers ::query()
* @covers ::isRaw()
* @covers ::buildRaw()
* @dataProvider typesProvider
*/
public function testPreparedStatementQuery($type)
{
$this->setType($type);
$this->database->query(
"SELECT * FROM <account> WHERE <user_name> = :user_name AND <age> = :age",
[
":user_name" => "John Smite",
":age" => 20
]
);
$this->assertQuery(
<<<EOD
SELECT *
FROM "account"
WHERE "user_name" = 'John Smite' AND "age" = 20
EOD,
$this->database->queryString
);
}
/**
* @covers ::query()
* @covers ::isRaw()
* @covers ::buildRaw()
*/
public function testQueryEscape()
{
$database = new Medoo([
'testMode' => true,
'prefix' => 'PREFIX_'
]);
$database->query("SELECT * FROM <account> WHERE <name> = '<John>'");
$this->assertQuery(
<<<EOD
SELECT *
FROM "PREFIX_account"
WHERE "name" = '<John>'
EOD,
$database->queryString
);
}
}
+123
View File
@@ -0,0 +1,123 @@
<?php
namespace Medoo\Tests;
use Medoo\Medoo;
use InvalidArgumentException;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class QuoteTest extends MedooTestCase
{
/**
* @covers ::quote()
* @dataProvider typesProvider
*/
public function testQuote($type)
{
$this->setType($type);
$quotedString = $this->database->quote("Co'mpl''ex \"st'\"ring");
$expected = [
'mysql' => <<<EOD
'Co\'mpl\'\'ex \"st\'\"ring'
EOD,
'mssql' => <<<EOD
'Co''mpl''''ex "st''"ring'
EOD,
'sqlite' => <<<EOD
'Co''mpl''''ex "st''"ring'
EOD,
'pgsql' => <<<EOD
'Co''mpl''''ex "st''"ring'
EOD,
'oracle' => <<<EOD
'Co''mpl''''ex "st''"ring'
EOD
];
$this->assertEquals($expected[$type], $quotedString);
}
/**
* @covers ::columnQuote()
*/
public function testColumnQuote()
{
$this->assertEquals('"ColumnName"', $this->database->columnQuote("ColumnName"));
$this->assertEquals('"Column"."name"', $this->database->columnQuote("Column.name"));
$this->assertEquals('"Column"."Name"', $this->database->columnQuote("Column.Name"));
$this->assertEquals('"ネーム"', $this->database->columnQuote("ネーム"));
}
public function columnNamesProvider(): array
{
return [
["9ColumnName"],
["@ColumnName"],
[".ColumnName"],
["ColumnName."],
["ColumnName (alias)"]
];
}
/**
* @covers ::columnQuote()
* @dataProvider columnNamesProvider
*/
public function testIncorrectColumnQuote($column)
{
$this->expectException(InvalidArgumentException::class);
$this->database->columnQuote($column);
}
/**
* @covers ::tableQuote()
*/
public function testTableQuote()
{
$this->assertEquals('"TableName"', $this->database->tableQuote("TableName"));
$this->assertEquals('"_table"', $this->database->tableQuote("_table"));
$this->assertEquals('"アカウント"', $this->database->tableQuote("アカウント"));
}
/**
* @covers ::tableQuote()
*/
public function testPrefixTableQuote()
{
$database = new Medoo([
'testMode' => true,
'prefix' => 'PREFIX_'
]);
$this->assertEquals('"PREFIX_TableName"', $database->tableQuote("TableName"));
}
public function tableNamesProvider(): array
{
return [
["9TableName"],
["@TableName"],
[".TableName"],
["TableName."],
["Table.name"]
];
}
/**
* @covers ::tableQuote()
* @dataProvider tableNamesProvider
*/
public function testIncorrectTableQuote($table)
{
$this->expectException(InvalidArgumentException::class);
$this->database->tableQuote($table);
}
}
+153
View File
@@ -0,0 +1,153 @@
<?php
namespace Medoo\Tests;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class RandTest extends MedooTestCase
{
/**
* @covers ::rand()
* @dataProvider typesProvider
*/
public function testRand($type)
{
$this->setType($type);
$this->database->rand("account", [
"user_name"
]);
$this->assertQuery([
'default' => <<<EOD
SELECT "user_name"
FROM "account"
ORDER BY RANDOM()
EOD,
'mysql' => <<<EOD
SELECT `user_name`
FROM `account`
ORDER BY RAND()
EOD,
'mssql' => <<<EOD
SELECT [user_name]
FROM [account]
ORDER BY NEWID()
EOD
], $this->database->queryString);
}
/**
* @covers ::rand()
* @dataProvider typesProvider
*/
public function testWhereRand($type)
{
$this->setType($type);
$this->database->rand("account", [
"user_name"
], [
"location" => "Tokyo"
]);
$this->assertQuery([
'default' => <<<EOD
SELECT "user_name"
FROM "account"
WHERE "location" = 'Tokyo'
ORDER BY RANDOM()
EOD,
'mysql' => <<<EOD
SELECT `user_name`
FROM `account`
WHERE `location` = 'Tokyo'
ORDER BY RAND()
EOD,
'mssql' => <<<EOD
SELECT [user_name]
FROM [account]
WHERE [location] = 'Tokyo'
ORDER BY NEWID()
EOD
], $this->database->queryString);
}
/**
* @covers ::rand()
* @dataProvider typesProvider
*/
public function testWhereWithJoinRand($type)
{
$this->setType($type);
$this->database->rand("account", [
"[>]album" => "user_id"
], [
"account.user_name"
], [
"album.location" => "Tokyo"
]);
$this->assertQuery([
'default' => <<<EOD
SELECT "account"."user_name"
FROM "account"
LEFT JOIN "album" USING ("user_id")
WHERE "album"."location" = 'Tokyo'
ORDER BY RANDOM()
EOD,
'mysql' => <<<EOD
SELECT `account`.`user_name`
FROM `account`
LEFT JOIN `album` USING (`user_id`)
WHERE `album`.`location` = 'Tokyo'
ORDER BY RAND()
EOD,
'mssql' => <<<EOD
SELECT [account].[user_name]
FROM [account]
LEFT JOIN [album] USING ([user_id])
WHERE [album].[location] = 'Tokyo'
ORDER BY NEWID()
EOD
], $this->database->queryString);
}
/**
* @covers ::rand()
* @dataProvider typesProvider
*/
public function testWithJoinRand($type)
{
$this->setType($type);
$this->database->rand("account", [
"[>]album" => "user_id"
], [
"account.user_name"
]);
$this->assertQuery([
'default' => <<<EOD
SELECT "account"."user_name"
FROM "account"
LEFT JOIN "album" USING ("user_id")
ORDER BY RANDOM()
EOD,
'mysql' => <<<EOD
SELECT `account`.`user_name`
FROM `account`
LEFT JOIN `album` USING (`user_id`)
ORDER BY RAND()
EOD,
'mssql' => <<<EOD
SELECT [account].[user_name]
FROM [account]
LEFT JOIN [album] USING ([user_id])
ORDER BY NEWID()
EOD
], $this->database->queryString);
}
}
+57
View File
@@ -0,0 +1,57 @@
<?php
namespace Medoo\Tests;
use Medoo\Medoo;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class RawTest extends MedooTestCase
{
/**
* @covers ::raw()
* @covers ::isRaw()
* @covers ::buildRaw()
* @dataProvider typesProvider
*/
public function testRawWithPlaceholder($type)
{
$this->setType($type);
$this->database->select('account', [
'score' => Medoo::raw('SUM(<age> + <experience>)')
]);
$this->assertQuery(
<<<EOD
SELECT SUM("age" + "experience") AS "score"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::raw()
* @covers ::isRaw()
* @covers ::buildRaw()
* @dataProvider typesProvider
*/
public function testRawWithSamePlaceholderName($type)
{
$this->setType($type);
$this->database->select('account', [
'system' => Medoo::raw("COUNT(<system> = 'window' OR <system> = 'mac')")
]);
$this->assertQuery(
<<<EOD
SELECT COUNT("system" = 'window' OR "system" = 'mac') AS "system"
FROM "account"
EOD,
$this->database->queryString
);
}
}
+55
View File
@@ -0,0 +1,55 @@
<?php
namespace Medoo\Tests;
use InvalidArgumentException;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class ReplaceTest extends MedooTestCase
{
/**
* @covers ::replace()
* @dataProvider typesProvider
*/
public function testReplace($type)
{
$this->setType($type);
$this->database->replace("account", [
"type" => [
"user" => "new_user",
"business" => "new_business"
],
"column" => [
"old_value" => "new_value"
]
], [
"user_id[>]" => 1000
]);
$this->assertQuery(
<<<EOD
UPDATE "account"
SET "type" = REPLACE("type", 'user', 'new_user'),
"type" = REPLACE("type", 'business', 'new_business'),
"column" = REPLACE("column", 'old_value', 'new_value')
WHERE "user_id" > 1000
EOD,
$this->database->queryString
);
}
/**
* @covers ::replace()
*/
public function testReplaceEmptyColumns()
{
$this->expectException(InvalidArgumentException::class);
$this->database->replace("account", [], [
"user_id[>]" => 1000
]);
}
}
+715
View File
@@ -0,0 +1,715 @@
<?php
namespace Medoo\Tests;
use Medoo\Medoo;
use InvalidArgumentException;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class SelectTest extends MedooTestCase
{
/**
* @covers ::select()
* @covers ::selectContext()
* @covers ::isJoin()
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectAll($type)
{
$this->setType($type);
$this->database->select("account", "*");
$this->assertQuery(
<<<EOD
SELECT * FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::select()
* @covers ::selectContext()
* @dataProvider typesProvider
*/
public function testSelectTableWithAlias($type)
{
$this->setType($type);
$this->database->select("account (user)", "name");
$this->assertQuery(
<<<EOD
SELECT "name"
FROM "account" @AS "user"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectSingleColumn($type)
{
$this->setType($type);
$this->database->select("account", "name");
$this->assertQuery(
<<<EOD
SELECT "name"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectColumns($type)
{
$this->setType($type);
$this->database->select("account", ["name", "id"]);
$this->assertQuery(
<<<EOD
SELECT "name","id"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectColumnsWithAlias($type)
{
$this->setType($type);
$this->database->select("account", ["name(nickname)", "id"]);
$this->assertQuery(
<<<EOD
SELECT "name" AS "nickname","id"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectColumnsWithType($type)
{
$this->setType($type);
$this->database->select("account", ["name[String]", "data [JSON]"]);
$this->assertQuery(
<<<EOD
SELECT "name","data"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectColumnsWithAliasAndType($type)
{
$this->setType($type);
$this->database->select("account", ["name (nickname) [String]", "data [JSON]"]);
$this->assertQuery(
<<<EOD
SELECT "name" AS "nickname","data"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectColumnsWithRaw($type)
{
$this->setType($type);
$this->database->select("account", [
"id [String]" => Medoo::raw("UUID()")
]);
$this->assertQuery(
<<<EOD
SELECT UUID() AS "id"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::select()
* @covers ::selectContext()
* @covers ::isJoin()
* @dataProvider typesProvider
*/
public function testSelectWithWhere($type)
{
$this->setType($type);
$this->database->select("account", [
"name",
"id"
], [
"ORDER" => "age"
]);
$this->assertQuery(
<<<EOD
SELECT "name","id"
FROM "account"
ORDER BY "age"
EOD,
$this->database->queryString
);
}
/**
* @covers ::select()
* @covers ::selectContext()
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithLeftJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[>]post" => "user_id"
], [
"account.name",
"post.title"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","post"."title"
FROM "account"
LEFT JOIN "post"
USING ("user_id")
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithRightJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[<]post" => "user_id"
], [
"account.name",
"post.title"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","post"."title"
FROM "account"
RIGHT JOIN "post"
USING ("user_id")
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithFullJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[<>]post" => "user_id"
], [
"account.name",
"post.title"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","post"."title"
FROM "account"
FULL JOIN "post"
USING ("user_id")
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithInnerJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[><]post" => "user_id"
], [
"account.name",
"post.title"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","post"."title"
FROM "account"
INNER JOIN "post"
USING ("user_id")
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithSameKeysJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[>]photo" => ["user_id", "avatar_id"],
], [
"account.name",
"photo.link"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","photo"."link"
FROM "account"
LEFT JOIN "photo"
USING ("user_id", "avatar_id")
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithKeyJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[>]post" => ["user_id" => "author_id"],
], [
"account.name",
"post.title"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","post"."title"
FROM "account"
LEFT JOIN "post"
ON "account"."user_id" = "post"."author_id"
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithAliasJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[>]post (main_post)" => ["user_id" => "author_id"],
], [
"account.name",
"main_post.title"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","main_post"."title"
FROM "account"
LEFT JOIN "post" @AS "main_post"
ON "account"."user_id" = "main_post"."author_id"
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithReferJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[>]post" => ["user_id" => "author_id"],
"[>]album" => ["post.author_id" => "user_id"],
], [
"account.name",
"post.title",
"album.link"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","post"."title","album"."link"
FROM "account"
LEFT JOIN "post"
ON "account"."user_id" = "post"."author_id"
LEFT JOIN "album"
ON "post"."author_id" = "album"."user_id"
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithMultipleConditionJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[>]album" => ["author_id" => "user_id"],
"[>]post" => [
"user_id" => "author_id",
"album.user_id" => "owner_id"
]
], [
"account.name",
"post.title",
"album.link"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","post"."title","album"."link"
FROM "account"
LEFT JOIN "album"
ON "account"."author_id" = "album"."user_id"
LEFT JOIN "post"
ON "account"."user_id" = "post"."author_id"
AND "album"."user_id" = "post"."owner_id"
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectWithAdditionalConditionJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[>]post" => [
"user_id" => "author_id",
"AND" => [
"post.id[>]" => 10
]
]
], [
"account.name",
"post.title"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","post"."title"
FROM "account"
LEFT JOIN "post"
ON "account"."user_id" = "post"."author_id"
AND "post"."id" > 10
EOD,
$this->database->queryString
);
}
/**
* @covers ::isJoin()
* @covers ::buildJoin()
* @dataProvider typesProvider
*/
public function testSelectRawJoin($type)
{
$this->setType($type);
$this->database->select("account", [
"[>]post" => Medoo::raw("ON <account.user_id> = <post.author_id>")
], [
"account.name",
"post.title"
]);
$this->assertQuery(
<<<EOD
SELECT "account"."name","post"."title"
FROM "account"
LEFT JOIN "post"
ON "account"."user_id" = "post"."author_id"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectAllWithJoin($type)
{
$this->setType($type);
$this->expectException(InvalidArgumentException::class);
$this->database->select("account", [
"[>]post" => "user_id"
], [
"account.*"
]);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectWithDataMapping($type)
{
$this->setType($type);
$this->database->select("post", [
"[>]account" => ["user_id"]
], [
"post.content",
"userData" => [
"account.user_id",
"account.email",
"meta" => [
"account.location",
"account.gender"
]
]
]);
$this->assertQuery(
<<<EOD
SELECT "post"."content","account"."user_id","account"."email","account"."location","account"."gender"
FROM "post"
LEFT JOIN "account"
USING ("user_id")
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectWithIndexMapping($type)
{
$this->setType($type);
$this->database->select("account", [
"user_id" => [
"name (nickname)",
"location"
]
]);
$this->assertQuery(
<<<EOD
SELECT "user_id","name" AS "nickname","location"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectWithDistinct($type)
{
$this->setType($type);
$this->database->select("account", [
"@location",
"nickname"
]);
$this->assertQuery(
<<<EOD
SELECT DISTINCT "location","nickname"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectWithDistinctDiffOrder($type)
{
$this->setType($type);
$this->database->select("account", [
"location",
"@nickname"
]);
$this->assertQuery(
<<<EOD
SELECT DISTINCT "nickname","location"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectWithUnicodeCharacter($type)
{
$this->setType($type);
$this->database->select("considérer", [
"name (名前)",
"положение (ロケーション)"
]);
$this->assertQuery(
<<<EOD
SELECT "name" AS "名前","положение" AS "ロケーション"
FROM "considérer"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectWithHyphenCharacter($type)
{
$this->setType($type);
$this->database->select("account", [
"nick-name"
]);
$this->assertQuery(
<<<EOD
SELECT "nick-name"
FROM "account"
EOD,
$this->database->queryString
);
}
/**
* @covers ::columnMap()
* @covers ::columnPush()
* @dataProvider typesProvider
*/
public function testSelectWithSingleCharacter($type)
{
$this->setType($type);
$this->database->select("a", [
"[>]e" => ["f"]
], [
"b (c)"
]);
$this->assertQuery(
<<<EOD
SELECT "b" AS "c"
FROM "a"
LEFT JOIN "e" USING ("f")
EOD,
$this->database->queryString
);
}
}
+91
View File
@@ -0,0 +1,91 @@
<?php
namespace Medoo\Tests;
use Medoo\Medoo;
/**
* @coversDefaultClass \Medoo\Medoo
*/
class UpdateTest extends MedooTestCase
{
/**
* @covers \Medoo\Medoo::update()
* @dataProvider typesProvider
*/
public function testUpdate($type)
{
$this->setType($type);
$objectData = new Foo();
$this->database->update("account", [
"type" => "user",
"money" => 23.2,
"age[+]" => 1,
"level[-]" => 5,
"score[*]" => 2,
"lang" => ["en", "fr"],
"lang [JSON]" => ["en", "fr"],
"is_locked" => true,
"uuid" => Medoo::raw("UUID()"),
"object" => $objectData
], [
"user_id[<]" => 1000
]);
$this->assertQuery([
'default' => <<<EOD
UPDATE "account"
SET "type" = 'user',
"money" = '23.2',
"age" = "age" + 1,
"level" = "level" - 5,
"score" = "score" * 2,
"lang" = 'a:2:{i:0;s:2:"en";i:1;s:2:"fr";}',
"lang" = '["en","fr"]',
"is_locked" = 1,
"uuid" = UUID(),
"object" = :MeD5_mK
WHERE "user_id" < 1000
EOD,
'mysql' => <<<EOD
UPDATE "account"
SET "type" = 'user',
"money" = '23.2',
"age" = "age" + 1,
"level" = "level" - 5,
"score" = "score" * 2,
"lang" = 'a:2:{i:0;s:2:\"en\";i:1;s:2:\"fr\";}',
"lang" = '[\"en\",\"fr\"]',
"is_locked" = 1,
"uuid" = UUID(),
"object" = :MeD5_mK
WHERE "user_id" < 1000
EOD,
], $this->database->queryString);
}
public function testOracleLOBsUpdate()
{
$this->setType("oracle");
$fp = fopen('README.md', 'r');
$this->database->update("ACCOUNT", [
"DATA" => $fp
], [
"ID" => 1
]);
$this->assertQuery(
<<<EOD
UPDATE "ACCOUNT"
SET "DATA" = EMPTY_BLOB()
WHERE "ID" = 1
RETURNING "DATA" INTO :MeD0_mK
EOD,
$this->database->queryString
);
}
}
File diff suppressed because it is too large Load Diff