@@ -55,6 +55,14 @@ class WireDatabasePDO extends Wire implements WireDatabase {
55
55
*/
56
56
protected $ pdo = null ;
57
57
58
+ /**
59
+ * Whether or not our _init() has been called for the current $pdo connection
60
+ *
61
+ * @var bool
62
+ *
63
+ */
64
+ protected $ init = false ;
65
+
58
66
/**
59
67
* PDO connection settings
60
68
*
@@ -99,6 +107,8 @@ public static function getInstance(Config $config) {
99
107
$ name = $ config ->dbName ;
100
108
$ socket = $ config ->dbSocket ;
101
109
$ charset = $ config ->dbCharset ;
110
+ $ initCommand = str_replace ('{charset} ' , $ charset , $ config ->dbInitCommand );
111
+
102
112
if ($ socket ) {
103
113
// if socket is provided ignore $host and $port and use $socket instead:
104
114
$ dsn = "mysql:unix_socket= $ socket;dbname= $ name; " ;
@@ -107,13 +117,18 @@ public static function getInstance(Config $config) {
107
117
$ port = $ config ->dbPort ;
108
118
if ($ port ) $ dsn .= ";port= $ port " ;
109
119
}
120
+
110
121
$ driver_options = array (
111
- \PDO ::MYSQL_ATTR_INIT_COMMAND => "SET NAMES ' $ charset' " ,
112
122
\PDO ::ATTR_ERRMODE => \PDO ::ERRMODE_EXCEPTION
113
- );
123
+ );
124
+
125
+ if ($ initCommand ) $ driver_options [\PDO ::MYSQL_ATTR_INIT_COMMAND ] = $ initCommand ;
126
+
114
127
$ database = new WireDatabasePDO ($ dsn , $ username , $ password , $ driver_options );
115
128
$ database ->setDebugMode ($ config ->debug );
116
129
$ config ->wire ($ database );
130
+ $ database ->_init ();
131
+
117
132
return $ database ;
118
133
}
119
134
@@ -134,7 +149,37 @@ public function __construct($dsn, $username = null, $password = null, array $dri
134
149
$ this ->pdoConfig ['pass ' ] = $ password ;
135
150
$ this ->pdoConfig ['options ' ] = $ driver_options ;
136
151
$ this ->pdo ();
137
- $ this ->queryLogMax = (int ) $ this ->wire ('config ' )->dbQueryLogMax ;
152
+ }
153
+
154
+ /**
155
+ * Additional initialization after DB connection established and Wire instance populated
156
+ *
157
+ * #pw-internal
158
+ *
159
+ */
160
+ public function _init () {
161
+ if ($ this ->init || !$ this ->isWired ()) return ;
162
+ $ this ->init = true ;
163
+ $ config = $ this ->wire ('config ' );
164
+ $ this ->queryLogMax = (int ) $ config ->dbQueryLogMax ;
165
+ $ sqlModes = $ config ->dbSqlModes ;
166
+ if (is_array ($ sqlModes )) {
167
+ // ["5.7.0" => "remove:mode1,mode2/add:mode3"]
168
+ foreach ($ sqlModes as $ minVersion => $ commands ) {
169
+ if (strpos ($ commands , '/ ' ) !== false ) {
170
+ $ commands = explode ('/ ' , $ commands );
171
+ } else {
172
+ $ commands = array ($ commands );
173
+ }
174
+ foreach ($ commands as $ modes ) {
175
+ $ modes = trim ($ modes );
176
+ if (empty ($ modes )) continue ;
177
+ $ action = 'set ' ;
178
+ if (strpos ($ modes , ': ' )) list ($ action , $ modes ) = explode (': ' , $ modes );
179
+ $ this ->sqlMode (trim ($ action ), trim ($ modes ), $ minVersion );
180
+ }
181
+ }
182
+ }
138
183
}
139
184
140
185
/**
@@ -148,12 +193,16 @@ public function __construct($dsn, $username = null, $password = null, array $dri
148
193
*
149
194
*/
150
195
public function pdo () {
151
- if (!$ this ->pdo ) $ this ->pdo = new \PDO (
152
- $ this ->pdoConfig ['dsn ' ],
153
- $ this ->pdoConfig ['user ' ],
154
- $ this ->pdoConfig ['pass ' ],
155
- $ this ->pdoConfig ['options ' ]
156
- );
196
+ if (!$ this ->pdo ) {
197
+ $ this ->init = false ;
198
+ $ this ->pdo = new \PDO (
199
+ $ this ->pdoConfig ['dsn ' ],
200
+ $ this ->pdoConfig ['user ' ],
201
+ $ this ->pdoConfig ['pass ' ],
202
+ $ this ->pdoConfig ['options ' ]
203
+ );
204
+ }
205
+ if (!$ this ->init ) $ this ->_init ();
157
206
return $ this ->pdo ;
158
207
}
159
208
@@ -731,4 +780,73 @@ public function getMaxIndexLength() {
731
780
return $ max ;
732
781
}
733
782
783
+ /**
784
+ * Get SQL mode, set SQL mode, add to existing SQL mode, or remove from existing SQL mode
785
+ *
786
+ * #pw-group-custom
787
+ *
788
+ * ~~~~~
789
+ * // Get SQL mode
790
+ * $mode = $database->sqlMode();
791
+ *
792
+ * // Add an SQL mode
793
+ * $database->sqlMode('add', 'STRICT_TRANS_TABLES');
794
+ *
795
+ * // Remove SQL mode if version at least 5.7.0
796
+ * $database->sqlMode('remove', 'ONLY_FULL_GROUP_BY', '5.7.0');
797
+ * ~~~~~
798
+ *
799
+ * @param string $action Specify "get", "set", "add" or "remove". (default="get")
800
+ * @param string $mode Mode string or CSV string with SQL mode(s), i.e. "STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY".
801
+ * This argument should be omitted when using the "get" action.
802
+ * @param string $minVersion Make the given action only apply if MySQL version is at least $minVersion, i.e. "5.7.0".
803
+ * @return string|bool Returns string in "get" action, boolean false if required version not present, or true otherwise.
804
+ * @throws WireException If given an invalid $action
805
+ *
806
+ */
807
+ public function sqlMode ($ action = 'get ' , $ mode = '' , $ minVersion = '' ) {
808
+
809
+ $ result = true ;
810
+ $ modes = array ();
811
+
812
+ if (empty ($ action )) $ action = 'get ' ;
813
+
814
+ if ($ action !== 'get ' && $ minVersion ) {
815
+ $ serverVersion = $ this ->getAttribute (\PDO ::ATTR_SERVER_VERSION );
816
+ if (version_compare ($ serverVersion , $ minVersion , '< ' )) return false ;
817
+ }
818
+
819
+ if ($ mode ) {
820
+ foreach (explode (', ' , $ mode ) as $ m ) {
821
+ $ modes [] = $ this ->escapeStr (strtoupper ($ this ->wire ('sanitizer ' )->fieldName ($ m )));
822
+ }
823
+ }
824
+
825
+ switch ($ action ) {
826
+ case 'get ' :
827
+ $ query = $ this ->pdo ()->query ("SELECT @@sql_mode " );
828
+ $ result = $ query ->fetchColumn ();
829
+ $ query ->closeCursor ();
830
+ break ;
831
+ case 'set ' :
832
+ $ modes = implode (', ' , $ modes );
833
+ $ result = $ modes ;
834
+ $ this ->pdo ()->exec ("SET sql_mode=' $ modes' " );
835
+ break ;
836
+ case 'add ' :
837
+ foreach ($ modes as $ m ) {
838
+ $ this ->pdo ()->exec ("SET sql_mode=(SELECT CONCAT(@@sql_mode,', $ m')) " );
839
+ }
840
+ break ;
841
+ case 'remove ' :
842
+ foreach ($ modes as $ m ) {
843
+ $ this ->pdo ()->exec ("SET sql_mode=(SELECT REPLACE(@@sql_mode,' $ m','')) " );
844
+ }
845
+ break ;
846
+ default :
847
+ throw new WireException ("Unknown action ' $ action' " );
848
+ }
849
+
850
+ return $ result ;
851
+ }
734
852
}
0 commit comments