Skip to content

Commit 8b7d408

Browse files
committed
Merge remote-tracking branch 'refs/remotes/origin/101-fix-silent-exceptions' into dev
# Conflicts: # src/Database/Connection.php
2 parents 1a0307d + 24ab8cb commit 8b7d408

File tree

3 files changed

+199
-24
lines changed

3 files changed

+199
-24
lines changed

README.md

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,6 @@ Update your **config/database.php's** default driver with the settings for the *
4747
return [
4848
...
4949

50-
'sybase' =>
51-
[
52-
'application_encoding' => false,
53-
'application_charset' => '',
54-
'database_charset' => ''
55-
],
5650

5751
'connections' => [
5852
...
@@ -67,7 +61,9 @@ return [
6761
'charset' => 'utf8',
6862
'prefix' => '',
6963
'cache_tables' => true,
70-
'cache_time' => 3600
64+
'cache_time' => 3600,
65+
'application_encoding' => false,
66+
'application_charset' => '',
7167
],
7268

7369
...
@@ -107,18 +103,13 @@ The file is usualy found in **/etc/freetds/freetds.conf**. Set the configuration
107103
## Configuring the charset conversion
108104
This package offers to method to charset conversion, it can be converted in application layer or in database layer, we offered both methods because it can be useful for debugging, to config the application layer conversion you need to set up the following entries on the `database.php` file. You can view an example of the application encoding setup below:
109105

110-
```database
111-
'sybase' =>
112-
[
113-
'application_encoding' => true,
114-
'application_charset' => '',
115-
'database_charset' => ''
116-
],
117106
```
118107
To use the database layer conversion add the property charset to connection configuration on the sybase configuration array
119108
120109
```charset
121110
'charset' => 'utf8',
111+
'application_encoding' => false,
112+
'application_charset' => '',
122113
```
123114

124115

src/Database/Connection.php

Lines changed: 182 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,72 @@ class Connection extends IlluminateConnection
2323
*
2424
* @var array
2525
*/
26-
private array $numeric = [
27-
'int', 'numeric', 'bigint', 'integer', 'smallint', 'tinyint', 'decimal', 'double', 'float', 'real', 'bit',
28-
'binary', 'varbinary', 'timestamp', 'money',
26+
private $numeric = [
27+
'int',
28+
'numeric',
29+
'bigint',
30+
'integer',
31+
'smallint',
32+
'tinyint',
33+
'decimal',
34+
'double',
35+
'float',
36+
'real',
37+
'bit',
38+
'binary',
39+
'varbinary',
40+
'timestamp',
41+
'money',
2942
];
3043

44+
45+
/**
46+
* @var string The application charset
47+
*/
48+
private $applicationCharset;
49+
50+
/**
51+
* @var string The database charset
52+
*/
53+
private $databaseCharset;
54+
55+
private $applicationEncoding = false;
56+
57+
/**
58+
* Create a new database connection instance.
59+
*
60+
* @param \PDO|\Closure $pdo
61+
* @param string $database
62+
* @param string $tablePrefix
63+
* @param array $config
64+
* @return void
65+
*/
66+
public function __construct($pdo, $database = '', $tablePrefix = '', array $config = [])
67+
{
68+
parent::__construct($pdo, $database, $tablePrefix, $config);
69+
$this->configureExtraSettings($config);
70+
}
71+
72+
/**
73+
* Configures the encoding for the connection.
74+
*
75+
* @param array $config
76+
* @return void
77+
*/
78+
public function configureExtraSettings($config = [])
79+
{
80+
$this->applicationEncoding = key_exists('application_encoding',$config) ? $config['application_encoding'] : false;
81+
if ($this->applicationEncoding)
82+
{
83+
if (!key_exists('application_charset',$config,) || !key_exists('database_charset',$config))
84+
{
85+
throw new \Exception('When application encoding is configured, you need to set up application_charset and database_charset');
86+
}
87+
$this->applicationCharset = $config['application_charset'];
88+
$this->databaseCharset = $config['charset'];
89+
}
90+
}
91+
3192
/**
3293
* Execute a Closure within a transaction.
3394
*
@@ -54,10 +115,10 @@ public function transaction(Closure $callback, $attempts = 1)
54115
$this->pdo->exec('COMMIT TRAN');
55116
}
56117

57-
// If we catch an exception, we will roll back so nothing gets messed
58-
// up in the database. Then we'll re-throw the exception so it can
59-
// be handled how the developer sees fit for their applications.
60-
catch (Exception $e) {
118+
// If we catch an exception, we will roll back so nothing gets messed
119+
// up in the database. Then we'll re-throw the exception so it can
120+
// be handled how the developer sees fit for their applications.
121+
catch (\Exception|\PDOException $e) {
61122
$this->pdo->exec('ROLLBACK TRAN');
62123

63124
throw $e;
@@ -210,7 +271,7 @@ private function compile(Builder $builder)
210271
}
211272
}
212273

213-
$cache = $builder->connection->config['cache_tables'];
274+
$cache = key_exists('cache_tables',$builder->connection->config) ? $builder->connection->config['cache_tables'] : false;
214275
$types = [];
215276

216277
foreach ($arrTables as $tables) {
@@ -305,7 +366,6 @@ private function compile(Builder $builder)
305366
}
306367
}
307368
}
308-
309369
return $keys;
310370
}
311371

@@ -349,9 +409,121 @@ private function queryString(string $tables)
349409

350410
/**
351411
* Get the default fetch mode for the connection.
412+
* Set new bindings with specified column types to Sybase.
352413
*
353-
* @return int
414+
* @param string $query
415+
* @param array $bindings
416+
* @return mixed $newBinds
417+
*/
418+
private function compileBindings($query, $bindings)
419+
{
420+
if (count($bindings) == 0) {
421+
return [];
422+
}
423+
424+
$bindings = $this->prepareBindings($bindings);
425+
$builder = $this->queryGrammar->getBuilder();
426+
427+
if ($builder != null) {
428+
return $this->compile($builder);
429+
} else {
430+
return $bindings;
431+
}
432+
}
433+
434+
/**
435+
* Set new bindings with specified column types to Sybase.
436+
*
437+
* It could compile again from bindings using PDO::PARAM, however, it has
438+
* no constants that deal with decimals, so the only way would be to put
439+
* PDO::PARAM_STR, which would put quotes.
440+
*
441+
* @link http://stackoverflow.com/questions/2718628/pdoparam-for-type-decimal
442+
*
443+
* @param string $query
444+
* @param array $bindings
445+
* @return string $query
354446
*/
447+
private function compileNewQuery($query, $bindings)
448+
{
449+
$newQuery = '';
450+
451+
$bindings = $this->compileBindings($query, $bindings);
452+
$partQuery = explode('?', $query);
453+
454+
$bindings = array_map(fn ($v) => gettype($v) === 'string' ? str_replace('\'', '\'\'', $v) : $v, $bindings);
455+
$bindings = array_map(fn ($v) => gettype($v) === 'string' ? "'{$v}'" : $v, $bindings);
456+
$bindings = array_map(fn ($v) => gettype($v) === 'NULL' ? 'NULL' : $v, $bindings);
457+
458+
$newQuery = join(array_map(fn ($k1, $k2) => $k1.$k2, $partQuery, $bindings));
459+
$newQuery = str_replace('[]', '', $newQuery);
460+
$application_encoding = $this->applicationEncoding;
461+
if (is_null($application_encoding) || $application_encoding == false) {
462+
return $newQuery;
463+
}
464+
$database_charset = $this->databaseCharset;
465+
$application_charset = $this->applicationCharset;
466+
if (is_null($database_charset) || is_null($application_charset)) {
467+
throw new \Exception('[SYBASE] Database Charset and App Charset not set');
468+
}
469+
$newQuery = mb_convert_encoding($newQuery, $database_charset, $application_charset);
470+
471+
return $newQuery;
472+
}
473+
474+
475+
/**
476+
* Run a select statement against the database.
477+
*
478+
* @param string $query
479+
* @param array $bindings
480+
* @param bool $useReadPdo
481+
* @return array
482+
*/
483+
public function select($query, $bindings = [], $useReadPdo = true)
484+
{
485+
return $this->run($query, $bindings, function (
486+
$query,
487+
$bindings
488+
) {
489+
if ($this->pretending()) {
490+
return [];
491+
}
492+
493+
$statement = $this->getPdo()->prepare($this->compileNewQuery(
494+
$query,
495+
$bindings
496+
));
497+
498+
$statement->execute();
499+
500+
$result = [];
501+
502+
do {
503+
$result += $statement->fetchAll($this->getFetchMode());
504+
} while ($statement->nextRowset());
505+
506+
$result = [...$result];
507+
508+
$application_encoding = $this->applicationEncoding;
509+
if (is_null($application_encoding) || $application_encoding == false) {
510+
return $result;
511+
}
512+
$database_charset = $this->databaseCharset;
513+
$application_charset = $this->applicationCharset;
514+
if (is_null($database_charset) || is_null($application_charset)) {
515+
throw new \Exception('[SYBASE] Database Charset and App Charset not set');
516+
}
517+
foreach ($result as &$r) {
518+
foreach ($r as $k => &$v) {
519+
$v = gettype($v) === 'string' ? mb_convert_encoding($v, $application_charset, $database_charset) : $v;
520+
}
521+
}
522+
523+
return $result;
524+
});
525+
}
526+
355527
public function getFetchMode()
356528
{
357529
return $this->fetchMode;

src/Database/Schema/Grammar.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,18 @@ public function compileDropIfExists(Blueprint $blueprint, Fluent $command)
266266
) DROP TABLE ".$blueprint->getTable();
267267
}
268268

269+
public function compileTables()
270+
{
271+
return "select
272+
o.name as name,
273+
user_name(o.uid) as [schema],
274+
cast(reserved_pages(db_id(), o.id) as bigint) * @@maxpagesize as size_bytes
275+
from sysobjects o
276+
where o.type = 'U'
277+
order by o.name
278+
";
279+
}
280+
269281
/**
270282
* Compile a drop column command.
271283
*

0 commit comments

Comments
 (0)