Browse Source

Support for views #409

Maurits van der Schee 6 years ago
parent
commit
da352c2a93

+ 19
- 16
src/Tqdev/PhpCrudApi/Column/Reflection/ReflectedDatabase.php View File

6
 class ReflectedDatabase implements \JsonSerializable
6
 class ReflectedDatabase implements \JsonSerializable
7
 {
7
 {
8
     private $name;
8
     private $name;
9
-    private $tableNames;
9
+    private $tableTypes;
10
 
10
 
11
-    public function __construct(String $name, array $tableNames)
11
+    public function __construct(String $name, array $tableTypes)
12
     {
12
     {
13
         $this->name = $name;
13
         $this->name = $name;
14
-        $this->tableNames = [];
15
-        foreach ($tableNames as $tableName) {
16
-            $this->tableNames[$tableName] = true;
17
-        }
14
+        $this->tableTypes = $tableTypes;
18
     }
15
     }
19
 
16
 
20
     public static function fromReflection(GenericReflection $reflection): ReflectedDatabase
17
     public static function fromReflection(GenericReflection $reflection): ReflectedDatabase
21
     {
18
     {
22
         $name = $reflection->getDatabaseName();
19
         $name = $reflection->getDatabaseName();
23
-        $tableNames = [];
20
+        $tableTypes = [];
24
         foreach ($reflection->getTables() as $table) {
21
         foreach ($reflection->getTables() as $table) {
25
             $tableName = $table['TABLE_NAME'];
22
             $tableName = $table['TABLE_NAME'];
23
+            $tableType = $table['TABLE_TYPE'];
26
             if (in_array($tableName, $reflection->getIgnoredTables())) {
24
             if (in_array($tableName, $reflection->getIgnoredTables())) {
27
                 continue;
25
                 continue;
28
             }
26
             }
29
-            $tableNames[$tableName] = true;
27
+            $tableTypes[$tableName] = $tableType;
30
         }
28
         }
31
-        return new ReflectedDatabase($name, array_keys($tableNames));
29
+        return new ReflectedDatabase($name, $tableTypes);
32
     }
30
     }
33
 
31
 
34
     public static function fromJson( /* object */$json): ReflectedDatabase
32
     public static function fromJson( /* object */$json): ReflectedDatabase
35
     {
33
     {
36
         $name = $json->name;
34
         $name = $json->name;
37
-        $tableNames = $json->tables;
38
-        return new ReflectedDatabase($name, $tableNames);
35
+        $tableTypes = (array) $json->tables;
36
+        return new ReflectedDatabase($name, $tableTypes);
39
     }
37
     }
40
 
38
 
41
     public function getName(): String
39
     public function getName(): String
45
 
43
 
46
     public function hasTable(String $tableName): bool
44
     public function hasTable(String $tableName): bool
47
     {
45
     {
48
-        return isset($this->tableNames[$tableName]);
46
+        return isset($this->tableTypes[$tableName]);
47
+    }
48
+
49
+    public function getType(String $tableName): String
50
+    {
51
+        return isset($this->tableTypes[$tableName]) ? $this->tableTypes[$tableName] : '';
49
     }
52
     }
50
 
53
 
51
     public function getTableNames(): array
54
     public function getTableNames(): array
52
     {
55
     {
53
-        return array_keys($this->tableNames);
56
+        return array_keys($this->tableTypes);
54
     }
57
     }
55
 
58
 
56
     public function removeTable(String $tableName): bool
59
     public function removeTable(String $tableName): bool
57
     {
60
     {
58
-        if (!isset($this->tableNames[$tableName])) {
61
+        if (!isset($this->tableTypes[$tableName])) {
59
             return false;
62
             return false;
60
         }
63
         }
61
-        unset($this->tableNames[$tableName]);
64
+        unset($this->tableTypes[$tableName]);
62
         return true;
65
         return true;
63
     }
66
     }
64
 
67
 
66
     {
69
     {
67
         return [
70
         return [
68
             'name' => $this->name,
71
             'name' => $this->name,
69
-            'tables' => array_keys($this->tableNames),
72
+            'tables' => $this->tableTypes,
70
         ];
73
         ];
71
     }
74
     }
72
 
75
 

+ 14
- 5
src/Tqdev/PhpCrudApi/Column/Reflection/ReflectedTable.php View File

6
 class ReflectedTable implements \JsonSerializable
6
 class ReflectedTable implements \JsonSerializable
7
 {
7
 {
8
     private $name;
8
     private $name;
9
+    private $type;
9
     private $columns;
10
     private $columns;
10
     private $pk;
11
     private $pk;
11
     private $fks;
12
     private $fks;
12
 
13
 
13
-    public function __construct(String $name, array $columns)
14
+    public function __construct(String $name, String $type, array $columns)
14
     {
15
     {
15
         $this->name = $name;
16
         $this->name = $name;
17
+        $this->type = $type;
16
         // set columns
18
         // set columns
17
         $this->columns = [];
19
         $this->columns = [];
18
         foreach ($columns as $column) {
20
         foreach ($columns as $column) {
37
         }
39
         }
38
     }
40
     }
39
 
41
 
40
-    public static function fromReflection(GenericReflection $reflection, String $name): ReflectedTable
42
+    public static function fromReflection(GenericReflection $reflection, String $name, String $type): ReflectedTable
41
     {
43
     {
42
         // set columns
44
         // set columns
43
         $columns = [];
45
         $columns = [];
44
-        foreach ($reflection->getTableColumns($name) as $tableColumn) {
46
+        foreach ($reflection->getTableColumns($name, $type) as $tableColumn) {
45
             $column = ReflectedColumn::fromReflection($reflection, $tableColumn);
47
             $column = ReflectedColumn::fromReflection($reflection, $tableColumn);
46
             $columns[$column->getName()] = $column;
48
             $columns[$column->getName()] = $column;
47
         }
49
         }
59
         foreach ($fks as $columnName => $table) {
61
         foreach ($fks as $columnName => $table) {
60
             $columns[$columnName]->setFk($table);
62
             $columns[$columnName]->setFk($table);
61
         }
63
         }
62
-        return new ReflectedTable($name, array_values($columns));
64
+        return new ReflectedTable($name, $type, array_values($columns));
63
     }
65
     }
64
 
66
 
65
     public static function fromJson( /* object */$json): ReflectedTable
67
     public static function fromJson( /* object */$json): ReflectedTable
66
     {
68
     {
67
         $name = $json->name;
69
         $name = $json->name;
70
+        $type = $json->type;
68
         $columns = [];
71
         $columns = [];
69
         if (isset($json->columns) && is_array($json->columns)) {
72
         if (isset($json->columns) && is_array($json->columns)) {
70
             foreach ($json->columns as $column) {
73
             foreach ($json->columns as $column) {
71
                 $columns[] = ReflectedColumn::fromJson($column);
74
                 $columns[] = ReflectedColumn::fromJson($column);
72
             }
75
             }
73
         }
76
         }
74
-        return new ReflectedTable($name, $columns);
77
+        return new ReflectedTable($name, $type, $columns);
75
     }
78
     }
76
 
79
 
77
     public function hasColumn(String $columnName): bool
80
     public function hasColumn(String $columnName): bool
94
         return $this->name;
97
         return $this->name;
95
     }
98
     }
96
 
99
 
100
+    public function getType(): String
101
+    {
102
+        return $this->type;
103
+    }
104
+
97
     public function columnNames(): array
105
     public function columnNames(): array
98
     {
106
     {
99
         return array_keys($this->columns);
107
         return array_keys($this->columns);
128
     {
136
     {
129
         return [
137
         return [
130
             'name' => $this->name,
138
             'name' => $this->name,
139
+            'type' => $this->type,
131
             'columns' => array_values($this->columns),
140
             'columns' => array_values($this->columns),
132
         ];
141
         ];
133
     }
142
     }

+ 7
- 1
src/Tqdev/PhpCrudApi/Column/ReflectionService.php View File

42
         if ($data != '') {
42
         if ($data != '') {
43
             $table = ReflectedTable::fromJson(json_decode(gzuncompress($data)));
43
             $table = ReflectedTable::fromJson(json_decode(gzuncompress($data)));
44
         } else {
44
         } else {
45
-            $table = ReflectedTable::fromReflection($this->db->reflection(), $tableName);
45
+            $tableType = $this->database->getType($tableName);
46
+            $table = ReflectedTable::fromReflection($this->db->reflection(), $tableName, $tableType);
46
             $data = gzcompress(json_encode($table, JSON_UNESCAPED_UNICODE));
47
             $data = gzcompress(json_encode($table, JSON_UNESCAPED_UNICODE));
47
             $this->cache->set("ReflectedTable($tableName)", $data, $this->ttl);
48
             $this->cache->set("ReflectedTable($tableName)", $data, $this->ttl);
48
         }
49
         }
64
         return $this->database->hasTable($tableName);
65
         return $this->database->hasTable($tableName);
65
     }
66
     }
66
 
67
 
68
+    public function getType(String $tableName): String
69
+    {
70
+        return $this->database->getType($tableName);
71
+    }
72
+
67
     public function getTable(String $tableName): ReflectedTable
73
     public function getTable(String $tableName): ReflectedTable
68
     {
74
     {
69
         if (!isset($this->tables[$tableName])) {
75
         if (!isset($this->tables[$tableName])) {

+ 29
- 14
src/Tqdev/PhpCrudApi/Controller/RecordController.php View File

37
     public function read(Request $request): Response
37
     public function read(Request $request): Response
38
     {
38
     {
39
         $table = $request->getPathSegment(2);
39
         $table = $request->getPathSegment(2);
40
-        $id = $request->getPathSegment(3);
41
-        $params = $request->getParams();
42
         if (!$this->service->hasTable($table)) {
40
         if (!$this->service->hasTable($table)) {
43
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
41
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
44
         }
42
         }
43
+        if ($this->service->getType($table) != 'table') {
44
+            return $this->responder->error(ErrorCode::OPERATION_NOT_SUPPORTED, __FUNCTION__);
45
+        }
46
+        $id = $request->getPathSegment(3);
47
+        $params = $request->getParams();
45
         if (strpos($id, ',') !== false) {
48
         if (strpos($id, ',') !== false) {
46
             $ids = explode(',', $id);
49
             $ids = explode(',', $id);
47
             $result = [];
50
             $result = [];
61
     public function create(Request $request): Response
64
     public function create(Request $request): Response
62
     {
65
     {
63
         $table = $request->getPathSegment(2);
66
         $table = $request->getPathSegment(2);
67
+        if (!$this->service->hasTable($table)) {
68
+            return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
69
+        }
70
+        if ($this->service->getType($table) != 'table') {
71
+            return $this->responder->error(ErrorCode::OPERATION_NOT_SUPPORTED, __FUNCTION__);
72
+        }
64
         $record = $request->getBody();
73
         $record = $request->getBody();
65
         if ($record === null) {
74
         if ($record === null) {
66
             return $this->responder->error(ErrorCode::HTTP_MESSAGE_NOT_READABLE, '');
75
             return $this->responder->error(ErrorCode::HTTP_MESSAGE_NOT_READABLE, '');
67
         }
76
         }
68
         $params = $request->getParams();
77
         $params = $request->getParams();
69
-        if (!$this->service->hasTable($table)) {
70
-            return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
71
-        }
72
         if (is_array($record)) {
78
         if (is_array($record)) {
73
             $result = array();
79
             $result = array();
74
             foreach ($record as $r) {
80
             foreach ($record as $r) {
83
     public function update(Request $request): Response
89
     public function update(Request $request): Response
84
     {
90
     {
85
         $table = $request->getPathSegment(2);
91
         $table = $request->getPathSegment(2);
92
+        if (!$this->service->hasTable($table)) {
93
+            return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
94
+        }
95
+        if ($this->service->getType($table) != 'table') {
96
+            return $this->responder->error(ErrorCode::OPERATION_NOT_SUPPORTED, __FUNCTION__);
97
+        }
86
         $id = $request->getPathSegment(3);
98
         $id = $request->getPathSegment(3);
99
+        $params = $request->getParams();
87
         $record = $request->getBody();
100
         $record = $request->getBody();
88
         if ($record === null) {
101
         if ($record === null) {
89
             return $this->responder->error(ErrorCode::HTTP_MESSAGE_NOT_READABLE, '');
102
             return $this->responder->error(ErrorCode::HTTP_MESSAGE_NOT_READABLE, '');
90
         }
103
         }
91
-        $params = $request->getParams();
92
-        if (!$this->service->hasTable($table)) {
93
-            return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
94
-        }
95
         $ids = explode(',', $id);
104
         $ids = explode(',', $id);
96
         if (is_array($record)) {
105
         if (is_array($record)) {
97
             if (count($ids) != count($record)) {
106
             if (count($ids) != count($record)) {
113
     public function delete(Request $request): Response
122
     public function delete(Request $request): Response
114
     {
123
     {
115
         $table = $request->getPathSegment(2);
124
         $table = $request->getPathSegment(2);
116
-        $id = $request->getPathSegment(3);
117
-        $params = $request->getParams();
118
         if (!$this->service->hasTable($table)) {
125
         if (!$this->service->hasTable($table)) {
119
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
126
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
120
         }
127
         }
128
+        if ($this->service->getType($table) != 'table') {
129
+            return $this->responder->error(ErrorCode::OPERATION_NOT_SUPPORTED, __FUNCTION__);
130
+        }
131
+        $id = $request->getPathSegment(3);
132
+        $params = $request->getParams();
121
         $ids = explode(',', $id);
133
         $ids = explode(',', $id);
122
         if (count($ids) > 1) {
134
         if (count($ids) > 1) {
123
             $result = array();
135
             $result = array();
133
     public function increment(Request $request): Response
145
     public function increment(Request $request): Response
134
     {
146
     {
135
         $table = $request->getPathSegment(2);
147
         $table = $request->getPathSegment(2);
148
+        if (!$this->service->hasTable($table)) {
149
+            return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
150
+        }
151
+        if ($this->service->getType($table) != 'table') {
152
+            return $this->responder->error(ErrorCode::OPERATION_NOT_SUPPORTED, __FUNCTION__);
153
+        }
136
         $id = $request->getPathSegment(3);
154
         $id = $request->getPathSegment(3);
137
         $record = $request->getBody();
155
         $record = $request->getBody();
138
         if ($record === null) {
156
         if ($record === null) {
139
             return $this->responder->error(ErrorCode::HTTP_MESSAGE_NOT_READABLE, '');
157
             return $this->responder->error(ErrorCode::HTTP_MESSAGE_NOT_READABLE, '');
140
         }
158
         }
141
         $params = $request->getParams();
159
         $params = $request->getParams();
142
-        if (!$this->service->hasTable($table)) {
143
-            return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
144
-        }
145
         $ids = explode(',', $id);
160
         $ids = explode(',', $id);
146
         if (is_array($record)) {
161
         if (is_array($record)) {
147
             if (count($ids) != count($record)) {
162
             if (count($ids) != count($record)) {

+ 30
- 7
src/Tqdev/PhpCrudApi/Database/GenericReflection.php View File

20
     {
20
     {
21
         switch ($this->driver) {
21
         switch ($this->driver) {
22
             case 'mysql':return [];
22
             case 'mysql':return [];
23
-            case 'pgsql':return ['spatial_ref_sys'];
23
+            case 'pgsql':return ['spatial_ref_sys', 'raster_columns', 'raster_overviews', 'geography_columns', 'geometry_columns'];
24
             case 'sqlsrv':return [];
24
             case 'sqlsrv':return [];
25
         }
25
         }
26
     }
26
     }
28
     private function getTablesSQL(): String
28
     private function getTablesSQL(): String
29
     {
29
     {
30
         switch ($this->driver) {
30
         switch ($this->driver) {
31
-            case 'mysql':return 'SELECT "TABLE_NAME" FROM "INFORMATION_SCHEMA"."TABLES" WHERE "TABLE_TYPE" IN (\'BASE TABLE\') AND "TABLE_SCHEMA" = ? ORDER BY BINARY "TABLE_NAME"';
32
-            case 'pgsql':return 'SELECT c.relname as "TABLE_NAME" FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN (\'r\') AND n.nspname <> \'pg_catalog\' AND n.nspname <> \'information_schema\' AND n.nspname !~ \'^pg_toast\' AND pg_catalog.pg_table_is_visible(c.oid) AND \'\' <> ? ORDER BY "TABLE_NAME";';
33
-            case 'sqlsrv':return 'SELECT o.name as "TABLE_NAME" FROM sysobjects o WHERE o.xtype = \'U\' ORDER BY "TABLE_NAME"';
31
+            case 'mysql':return 'SELECT "TABLE_NAME", "TABLE_TYPE" FROM "INFORMATION_SCHEMA"."TABLES" WHERE "TABLE_TYPE" IN (\'BASE TABLE\' , \'VIEW\') AND "TABLE_SCHEMA" = ? ORDER BY BINARY "TABLE_NAME"';
32
+            case 'pgsql':return 'SELECT c.relname as "TABLE_NAME", c.relkind as "TABLE_TYPE" FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN (\'r\', \'v\') AND n.nspname <> \'pg_catalog\' AND n.nspname <> \'information_schema\' AND n.nspname !~ \'^pg_toast\' AND pg_catalog.pg_table_is_visible(c.oid) AND \'\' <> ? ORDER BY "TABLE_NAME";';
33
+            case 'sqlsrv':return 'SELECT o.name as "TABLE_NAME", o.xtype as "TABLE_TYPE" FROM sysobjects o WHERE o.xtype IN (\'U\', \'V\') ORDER BY "TABLE_NAME"';
34
         }
34
         }
35
     }
35
     }
36
 
36
 
69
     public function getTables(): array
69
     public function getTables(): array
70
     {
70
     {
71
         $sql = $this->getTablesSQL();
71
         $sql = $this->getTablesSQL();
72
-        return $this->query($sql, [$this->database]);
72
+        $results = $this->query($sql, [$this->database]);
73
+        foreach ($results as &$result) {
74
+            switch ($this->driver) {
75
+                case 'mysql':
76
+                    $map = ['BASE TABLE' => 'table', 'VIEW' => 'view'];
77
+                    $result['TABLE_TYPE'] = $map[$result['TABLE_TYPE']];
78
+                    break;
79
+                case 'pgsql':
80
+                    $map = ['r' => 'table', 'v' => 'view'];
81
+                    $result['TABLE_TYPE'] = $map[$result['TABLE_TYPE']];
82
+                    break;
83
+                case 'sqlsrv':
84
+                    $map = ['U' => 'table', 'V' => 'view'];
85
+                    $result['TABLE_TYPE'] = $map[trim($result['TABLE_TYPE'])];
86
+                    break;
87
+            }
88
+        }
89
+        return $results;
73
     }
90
     }
74
 
91
 
75
-    public function getTableColumns(String $tableName): array
92
+    public function getTableColumns(String $tableName, String $type): array
76
     {
93
     {
77
         $sql = $this->getTableColumnsSQL();
94
         $sql = $this->getTableColumnsSQL();
78
-        return $this->query($sql, [$tableName, $this->database]);
95
+        $results = $this->query($sql, [$tableName, $this->database]);
96
+        if ($type == 'view') {
97
+            foreach ($results as &$result) {
98
+                $result['IS_NULLABLE'] = false;
99
+            }
100
+        }
101
+        return $results;
79
     }
102
     }
80
 
103
 
81
     public function getTablePrimaryKeys(String $tableName): array
104
     public function getTablePrimaryKeys(String $tableName): array

+ 4
- 0
src/Tqdev/PhpCrudApi/OpenApi/OpenApiBuilder.php View File

87
     private function setPath(String $tableName) /*: void*/
87
     private function setPath(String $tableName) /*: void*/
88
     {
88
     {
89
         $table = $this->reflection->getTable($tableName);
89
         $table = $this->reflection->getTable($tableName);
90
+        $type = $table->getType($tableName);
90
         $pk = $table->getPk();
91
         $pk = $table->getPk();
91
         $pkName = $pk ? $pk->getName() : '';
92
         $pkName = $pk ? $pk->getName() : '';
92
         foreach ($this->operations as $operation => $method) {
93
         foreach ($this->operations as $operation => $method) {
93
             if (!$pkName && $operation != 'list') {
94
             if (!$pkName && $operation != 'list') {
94
                 continue;
95
                 continue;
95
             }
96
             }
97
+            if ($type != 'table' && $operation != 'list') {
98
+                continue;
99
+            }
96
             if (!$this->isOperationOnTableAllowed($operation, $tableName)) {
100
             if (!$this->isOperationOnTableAllowed($operation, $tableName)) {
97
                 continue;
101
                 continue;
98
             }
102
             }

+ 2
- 0
src/Tqdev/PhpCrudApi/Record/ErrorCode.php View File

26
     const ACCESS_DENIED = 1012;
26
     const ACCESS_DENIED = 1012;
27
     const INPUT_VALIDATION_FAILED = 1013;
27
     const INPUT_VALIDATION_FAILED = 1013;
28
     const OPERATION_FORBIDDEN = 1014;
28
     const OPERATION_FORBIDDEN = 1014;
29
+    const OPERATION_NOT_SUPPORTED = 1015;
29
 
30
 
30
     private $values = [
31
     private $values = [
31
         9999 => ["%s", Response::INTERNAL_SERVER_ERROR],
32
         9999 => ["%s", Response::INTERNAL_SERVER_ERROR],
44
         1012 => ["Access denied for '%s'", Response::FORBIDDEN],
45
         1012 => ["Access denied for '%s'", Response::FORBIDDEN],
45
         1013 => ["Input validation failed for '%s'", Response::UNPROCESSABLE_ENTITY],
46
         1013 => ["Input validation failed for '%s'", Response::UNPROCESSABLE_ENTITY],
46
         1014 => ["Operation forbidden", Response::FORBIDDEN],
47
         1014 => ["Operation forbidden", Response::FORBIDDEN],
48
+        1015 => ["Operation '%s' not supported", Response::METHOD_NOT_ALLOWED],
47
     ];
49
     ];
48
 
50
 
49
     public function __construct(int $code)
51
     public function __construct(int $code)

+ 5
- 0
src/Tqdev/PhpCrudApi/Record/RecordService.php View File

50
         return $this->reflection->hasTable($table);
50
         return $this->reflection->hasTable($table);
51
     }
51
     }
52
 
52
 
53
+    public function getType(String $table): bool
54
+    {
55
+        return $this->reflection->getType($table);
56
+    }
57
+
53
     public function create(String $tableName, /* object */ $record, array $params)
58
     public function create(String $tableName, /* object */ $record, array $params)
54
     {
59
     {
55
         $this->sanitizeRecord($tableName, $record, '');
60
         $this->sanitizeRecord($tableName, $record, '');

+ 1
- 1
src/Tqdev/PhpCrudApi/Response.php View File

7
     const UNAUTHORIZED = 401;
7
     const UNAUTHORIZED = 401;
8
     const FORBIDDEN = 403;
8
     const FORBIDDEN = 403;
9
     const NOT_FOUND = 404;
9
     const NOT_FOUND = 404;
10
+    const METHOD_NOT_ALLOWED = 405;
10
     const CONFLICT = 409;
11
     const CONFLICT = 409;
11
     const UNPROCESSABLE_ENTITY = 422;
12
     const UNPROCESSABLE_ENTITY = 422;
12
     const INTERNAL_SERVER_ERROR = 500;
13
     const INTERNAL_SERVER_ERROR = 500;
13
-
14
     private $status;
14
     private $status;
15
     private $headers;
15
     private $headers;
16
     private $body;
16
     private $body;

+ 10
- 4
tests/fixtures/blog_sqlsrv.sql View File

1
+IF (OBJECT_ID('FK_kunsthåndværk_users', 'F') IS NOT NULL)
2
+BEGIN
3
+ALTER TABLE [kunsthåndværk] DROP	CONSTRAINT [FK_kunsthåndværk_users]
4
+END
5
+GO
6
+
1
 IF (OBJECT_ID('FK_barcodes_products', 'F') IS NOT NULL)
7
 IF (OBJECT_ID('FK_barcodes_products', 'F') IS NOT NULL)
2
 BEGIN
8
 BEGIN
3
 ALTER TABLE [barcodes] DROP	CONSTRAINT [FK_barcodes_products]
9
 ALTER TABLE [barcodes] DROP	CONSTRAINT [FK_barcodes_products]
222
 GO
228
 GO
223
 
229
 
224
 CREATE TABLE [kunsthåndværk](
230
 CREATE TABLE [kunsthåndværk](
225
-	[id] [nvarchar](36),
231
+	[id] [nvarchar](36) NOT NULL,
226
 	[Umlauts ä_ö_ü-COUNT] [int] NOT NULL,
232
 	[Umlauts ä_ö_ü-COUNT] [int] NOT NULL,
227
 	[user_id] [int] NOT NULL,
233
 	[user_id] [int] NOT NULL,
228
 	[invisible] [nvarchar](36),
234
 	[invisible] [nvarchar](36),
232
 GO
238
 GO
233
 
239
 
234
 CREATE TABLE [invisibles](
240
 CREATE TABLE [invisibles](
235
-	[id] [nvarchar](36),
241
+	[id] [nvarchar](36) NOT NULL,
236
 	CONSTRAINT [PK_invisibles]
242
 	CONSTRAINT [PK_invisibles]
237
 	PRIMARY KEY CLUSTERED([id] ASC)
243
 	PRIMARY KEY CLUSTERED([id] ASC)
238
 )
244
 )
239
 GO
245
 GO
240
 
246
 
241
 CREATE TABLE [nopk](
247
 CREATE TABLE [nopk](
242
-	[id] [nvarchar](36)
248
+	[id] [nvarchar](36) NOT NULL
243
 )
249
 )
244
 GO
250
 GO
245
 
251
 
349
 REFERENCES [users] ([id])
355
 REFERENCES [users] ([id])
350
 GO
356
 GO
351
 ALTER TABLE [kunsthåndværk] CHECK	CONSTRAINT [FK_kunsthåndværk_users]
357
 ALTER TABLE [kunsthåndværk] CHECK	CONSTRAINT [FK_kunsthåndværk_users]
352
-GO
358
+GO

+ 2
- 2
tests/functional/003_columns/001_get_database.log View File

2
 ===
2
 ===
3
 200
3
 200
4
 Content-Type: application/json
4
 Content-Type: application/json
5
-Content-Length: 2273
5
+Content-Length: 2579
6
 
6
 
7
-{"name":"php-crud-api","tables":[{"name":"barcodes","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]},{"name":"categories","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"icon","type":"blob","nullable":true}]},{"name":"comments","columns":[{"name":"id","type":"integer","pk":true},{"name":"post_id","type":"integer","fk":"posts"},{"name":"message","type":"varchar","length":255}]},{"name":"countries","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"shape","type":"geometry"}]},{"name":"events","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"datetime","type":"timestamp"},{"name":"visitors","type":"integer"}]},{"name":"kunsthåndværk","columns":[{"name":"id","type":"varchar","length":36,"pk":true},{"name":"Umlauts ä_ö_ü-COUNT","type":"integer"},{"name":"user_id","type":"integer","fk":"users"}]},{"name":"nopk","columns":[{"name":"id","type":"varchar","length":36}]},{"name":"post_tags","columns":[{"name":"id","type":"integer","pk":true},{"name":"post_id","type":"integer","fk":"posts"},{"name":"tag_id","type":"integer","fk":"tags"}]},{"name":"posts","columns":[{"name":"id","type":"integer","pk":true},{"name":"user_id","type":"integer","fk":"users"},{"name":"category_id","type":"integer","fk":"categories"},{"name":"content","type":"varchar","length":255}]},{"name":"products","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"price","type":"decimal","precision":10,"scale":2},{"name":"properties","type":"clob"},{"name":"created_at","type":"timestamp"},{"name":"deleted_at","type":"timestamp","nullable":true}]},{"name":"tags","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"is_important","type":"boolean"}]},{"name":"users","columns":[{"name":"id","type":"integer","pk":true},{"name":"username","type":"varchar","length":255},{"name":"password","type":"varchar","length":255},{"name":"location","type":"geometry","nullable":true}]}]}
7
+{"name":"php-crud-api","tables":[{"name":"barcodes","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]},{"name":"categories","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"icon","type":"blob","nullable":true}]},{"name":"comments","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"post_id","type":"integer","fk":"posts"},{"name":"message","type":"varchar","length":255}]},{"name":"countries","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"shape","type":"geometry"}]},{"name":"events","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"datetime","type":"timestamp"},{"name":"visitors","type":"integer"}]},{"name":"kunsthåndværk","type":"table","columns":[{"name":"id","type":"varchar","length":36,"pk":true},{"name":"Umlauts ä_ö_ü-COUNT","type":"integer"},{"name":"user_id","type":"integer","fk":"users"}]},{"name":"nopk","type":"table","columns":[{"name":"id","type":"varchar","length":36}]},{"name":"post_tags","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"post_id","type":"integer","fk":"posts"},{"name":"tag_id","type":"integer","fk":"tags"}]},{"name":"posts","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"user_id","type":"integer","fk":"users"},{"name":"category_id","type":"integer","fk":"categories"},{"name":"content","type":"varchar","length":255}]},{"name":"products","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"price","type":"decimal","precision":10,"scale":2},{"name":"properties","type":"clob"},{"name":"created_at","type":"timestamp"},{"name":"deleted_at","type":"timestamp","nullable":true}]},{"name":"tag_usage","type":"view","columns":[{"name":"name","type":"varchar","length":255},{"name":"count","type":"bigint"}]},{"name":"tags","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"name","type":"varchar","length":255},{"name":"is_important","type":"boolean"}]},{"name":"users","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"username","type":"varchar","length":255},{"name":"password","type":"varchar","length":255},{"name":"location","type":"geometry","nullable":true}]}]}

+ 2
- 2
tests/functional/003_columns/002_get_barcodes_table.log View File

2
 ===
2
 ===
3
 200
3
 200
4
 Content-Type: application/json
4
 Content-Type: application/json
5
-Content-Length: 201
5
+Content-Length: 216
6
 
6
 
7
-{"name":"barcodes","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}
7
+{"name":"barcodes","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}

+ 4
- 4
tests/functional/003_columns/008_update_barcodes_table.log View File

12
 ===
12
 ===
13
 200
13
 200
14
 Content-Type: application/json
14
 Content-Type: application/json
15
-Content-Length: 202
15
+Content-Length: 217
16
 
16
 
17
-{"name":"barcodes2","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}
17
+{"name":"barcodes2","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}
18
 ===
18
 ===
19
 PUT /columns/barcodes2
19
 PUT /columns/barcodes2
20
 
20
 
30
 ===
30
 ===
31
 200
31
 200
32
 Content-Type: application/json
32
 Content-Type: application/json
33
-Content-Length: 201
33
+Content-Length: 216
34
 
34
 
35
-{"name":"barcodes","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}
35
+{"name":"barcodes","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}

+ 3
- 3
tests/functional/003_columns/010_create_barcodes_table.log View File

1
 POST /columns
1
 POST /columns
2
 
2
 
3
-{"name":"barcodes2","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}
3
+{"name":"barcodes2","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}
4
 ===
4
 ===
5
 200
5
 200
6
 Content-Type: application/json
6
 Content-Type: application/json
12
 ===
12
 ===
13
 200
13
 200
14
 Content-Type: application/json
14
 Content-Type: application/json
15
-Content-Length: 202
15
+Content-Length: 217
16
 
16
 
17
-{"name":"barcodes2","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}
17
+{"name":"barcodes2","type":"table","columns":[{"name":"id","type":"integer","pk":true},{"name":"product_id","type":"integer","fk":"products"},{"name":"hex","type":"varchar","length":255},{"name":"bin","type":"blob"}]}
18
 ===
18
 ===
19
 DELETE /columns/barcodes2
19
 DELETE /columns/barcodes2
20
 ===
20
 ===

Loading…
Cancel
Save