@@ -1112,3 +1112,384 @@ async fn test_issue_303() -> Result<()> {
11121112
11131113 Ok ( ( ) )
11141114}
1115+
1116+ #[ tokio:: test]
1117+ async fn test_issue_328 ( ) -> Result < ( ) > {
1118+ let factory = ServerFactory :: default ( ) ;
1119+ let mut fs = MemoryFileSystem :: default ( ) ;
1120+ let test_db = get_new_test_db ( ) . await ;
1121+
1122+ let setup = r#"
1123+ create table public.users (
1124+ id serial primary key,
1125+ name varchar(255) not null
1126+ );
1127+ "# ;
1128+
1129+ test_db
1130+ . execute ( setup)
1131+ . await
1132+ . expect ( "Failed to setup test database" ) ;
1133+
1134+ let mut conf = PartialConfiguration :: init ( ) ;
1135+ conf. merge_with ( PartialConfiguration {
1136+ db : Some ( PartialDatabaseConfiguration {
1137+ database : Some (
1138+ test_db
1139+ . connect_options ( )
1140+ . get_database ( )
1141+ . unwrap ( )
1142+ . to_string ( ) ,
1143+ ) ,
1144+ ..Default :: default ( )
1145+ } ) ,
1146+ ..Default :: default ( )
1147+ } ) ;
1148+ fs. insert (
1149+ url ! ( "postgrestools.jsonc" ) . to_file_path ( ) . unwrap ( ) ,
1150+ serde_json:: to_string_pretty ( & conf) . unwrap ( ) ,
1151+ ) ;
1152+
1153+ let ( service, client) = factory
1154+ . create_with_fs ( None , DynRef :: Owned ( Box :: new ( fs) ) )
1155+ . into_inner ( ) ;
1156+
1157+ let ( stream, sink) = client. split ( ) ;
1158+ let mut server = Server :: new ( service) ;
1159+
1160+ let ( sender, mut receiver) = channel ( CHANNEL_BUFFER_SIZE ) ;
1161+ let reader = tokio:: spawn ( client_handler ( stream, sink, sender) ) ;
1162+
1163+ server. initialize ( ) . await ?;
1164+ server. initialized ( ) . await ?;
1165+
1166+ server. load_configuration ( ) . await ?;
1167+
1168+ server
1169+ . open_document ( "-- Create the company table\n CREATE TABLE company (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n name VARCHAR(255) NOT NULL,\n email VARCHAR(255) UNIQUE NOT NULL\n );\n \n -- Create the business table\n CREATE TABLE business (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n name VARCHAR(255) NOT NULL,\n email VARCHAR(255) UNIQUE NOT NULL,\n company_id UUID REFERENCES company(id) NOT NULL,\n INDEX (company_id)\n );" )
1170+ . await ?;
1171+
1172+ let notification = tokio:: time:: timeout ( Duration :: from_secs ( 5 ) , async {
1173+ loop {
1174+ match receiver. next ( ) . await {
1175+ Some ( ServerNotification :: PublishDiagnostics ( msg) ) => {
1176+ if msg
1177+ . diagnostics
1178+ . iter ( )
1179+ . any ( |d| d. message . contains ( "column \" unknown\" does not exist" ) )
1180+ {
1181+ return true ;
1182+ }
1183+ }
1184+ _ => continue ,
1185+ }
1186+ }
1187+ } )
1188+ . await
1189+ . is_ok ( ) ;
1190+
1191+ assert ! ( notification, "expected diagnostics for unknown column" ) ;
1192+
1193+ server. shutdown ( ) . await ?;
1194+ reader. abort ( ) ;
1195+
1196+ Ok ( ( ) )
1197+ }
1198+
1199+ #[ tokio:: test]
1200+ async fn test_issue_327 ( ) -> Result < ( ) > {
1201+ let factory = ServerFactory :: default ( ) ;
1202+ let mut fs = MemoryFileSystem :: default ( ) ;
1203+ let test_db = get_new_test_db ( ) . await ;
1204+
1205+ let setup = r#"
1206+ create table public.users (
1207+ id serial primary key,
1208+ name varchar(255) not null
1209+ );
1210+ "# ;
1211+
1212+ test_db
1213+ . execute ( setup)
1214+ . await
1215+ . expect ( "Failed to setup test database" ) ;
1216+
1217+ let mut conf = PartialConfiguration :: init ( ) ;
1218+ conf. merge_with ( PartialConfiguration {
1219+ db : Some ( PartialDatabaseConfiguration {
1220+ database : Some (
1221+ test_db
1222+ . connect_options ( )
1223+ . get_database ( )
1224+ . unwrap ( )
1225+ . to_string ( ) ,
1226+ ) ,
1227+ ..Default :: default ( )
1228+ } ) ,
1229+ ..Default :: default ( )
1230+ } ) ;
1231+ fs. insert (
1232+ url ! ( "postgrestools.jsonc" ) . to_file_path ( ) . unwrap ( ) ,
1233+ serde_json:: to_string_pretty ( & conf) . unwrap ( ) ,
1234+ ) ;
1235+
1236+ let ( service, client) = factory
1237+ . create_with_fs ( None , DynRef :: Owned ( Box :: new ( fs) ) )
1238+ . into_inner ( ) ;
1239+
1240+ let ( stream, sink) = client. split ( ) ;
1241+ let mut server = Server :: new ( service) ;
1242+
1243+ let ( sender, _) = channel ( CHANNEL_BUFFER_SIZE ) ;
1244+ let reader = tokio:: spawn ( client_handler ( stream, sink, sender) ) ;
1245+
1246+ server. initialize ( ) . await ?;
1247+ server. initialized ( ) . await ?;
1248+
1249+ server. load_configuration ( ) . await ?;
1250+
1251+ // Initial document content - a complex SQL file with multiple statements
1252+ let initial_content = r#"/* https://supabase.com/docs/guides/database/postgres/custom-claims-and-role-based-access-control-rbac#create-a-table-to-track-user-roles-and-permissions */
1253+ -----------------------------
1254+ /* User Permission Levels */
1255+ ---------------------------
1256+ CREATE TYPE public.user_permission_level
1257+ AS ENUM('admin', 'manager', 'member');
1258+
1259+
1260+ CREATE SCHEMA private;
1261+
1262+ sadjhkyjcxv sd 23
1263+
1264+
1265+ CREATE TABLE private.user_permission_levels (
1266+ user_id UUID PRIMARY KEY,
1267+ permission_level user_permission_level NOT NULL,
1268+
1269+ CONSTRAINT "user_permission_levels_user_id_fkey"
1270+ FOREIGN KEY (user_id)
1271+ REFERENCES auth.users (id)
1272+ ON UPDATE CASCADE
1273+ ON DELETE CASCADE
1274+ );
1275+
1276+
1277+ COMMENT ON TABLE private.user_permission_levels
1278+ IS 'Permission levels for each user.';
1279+
1280+
1281+ /*
1282+ ALTER TABLE private.user_permission_levels ENABLE ROW LEVEL SECURITY; */
1283+ /*
1284+ GRANT ALL ON TABLE private.user_permission_levels TO supabase_auth_admin; */
1285+ /* CREATE POLICY "Allow auth admin to read user permission levels" ON private.user_permission_levels FOR
1286+ SELECT
1287+ TO supabase_auth_admin USING (TRUE); */
1288+ /* */
1289+ -------------------------------
1290+ /* Custom Access Token Hook */
1291+ /* Executed while building JWT for user access token */
1292+ /* Must be enabled in Supabase Dashboard (for managed) or in config.toml (for local dev) */
1293+ ------------------------------------------------------------------------------------------"# ;
1294+
1295+ server
1296+ . open_named_document ( initial_content, url ! ( "document.sql" ) )
1297+ . await ?;
1298+
1299+ server
1300+ . change_document (
1301+ 21 ,
1302+ vec ! [ TextDocumentContentChangeEvent {
1303+ range: Some ( Range {
1304+ start: Position {
1305+ line: 9 ,
1306+ character: 0 ,
1307+ } ,
1308+ end: Position {
1309+ line: 10 ,
1310+ character: 17 ,
1311+ } ,
1312+ } ) ,
1313+ range_length: Some ( 19 ) ,
1314+ text: "" . to_string( ) ,
1315+ } ] ,
1316+ )
1317+ . await ?;
1318+
1319+ server
1320+ . change_document (
1321+ 22 ,
1322+ vec ! [ TextDocumentContentChangeEvent {
1323+ range: Some ( Range {
1324+ start: Position {
1325+ line: 8 ,
1326+ character: 22 ,
1327+ } ,
1328+ end: Position {
1329+ line: 9 ,
1330+ character: 0 ,
1331+ } ,
1332+ } ) ,
1333+ range_length: Some ( 2 ) ,
1334+ text: "" . to_string( ) ,
1335+ } ] ,
1336+ )
1337+ . await ?;
1338+
1339+ server
1340+ . change_document (
1341+ 50 ,
1342+ vec ! [ TextDocumentContentChangeEvent {
1343+ range: Some ( Range {
1344+ start: Position {
1345+ line: 0 ,
1346+ character: 0 ,
1347+ } ,
1348+ end: Position {
1349+ line: 0 ,
1350+ character: 0 ,
1351+ } ,
1352+ } ) ,
1353+ range_length: Some ( 0 ) ,
1354+ text: "-" . to_string( ) ,
1355+ } ] ,
1356+ )
1357+ . await ?;
1358+
1359+ server
1360+ . change_document (
1361+ 51 ,
1362+ vec ! [ TextDocumentContentChangeEvent {
1363+ range: Some ( Range {
1364+ start: Position {
1365+ line: 0 ,
1366+ character: 1 ,
1367+ } ,
1368+ end: Position {
1369+ line: 0 ,
1370+ character: 1 ,
1371+ } ,
1372+ } ) ,
1373+ range_length: Some ( 0 ) ,
1374+ text: "-" . to_string( ) ,
1375+ } ] ,
1376+ )
1377+ . await ?;
1378+
1379+ server
1380+ . change_document (
1381+ 52 ,
1382+ vec ! [ TextDocumentContentChangeEvent {
1383+ range: Some ( Range {
1384+ start: Position {
1385+ line: 0 ,
1386+ character: 2 ,
1387+ } ,
1388+ end: Position {
1389+ line: 0 ,
1390+ character: 2 ,
1391+ } ,
1392+ } ) ,
1393+ range_length: Some ( 0 ) ,
1394+ text: " " . to_string( ) ,
1395+ } ] ,
1396+ )
1397+ . await ?;
1398+
1399+ server
1400+ . change_document (
1401+ 57 ,
1402+ vec ! [
1403+ TextDocumentContentChangeEvent {
1404+ range: Some ( Range {
1405+ start: Position {
1406+ line: 33 ,
1407+ character: 0 ,
1408+ } ,
1409+ end: Position {
1410+ line: 33 ,
1411+ character: 0 ,
1412+ } ,
1413+ } ) ,
1414+ range_length: Some ( 0 ) ,
1415+ text: "-" . to_string( ) ,
1416+ } ,
1417+ TextDocumentContentChangeEvent {
1418+ range: Some ( Range {
1419+ start: Position {
1420+ line: 32 ,
1421+ character: 0 ,
1422+ } ,
1423+ end: Position {
1424+ line: 32 ,
1425+ character: 0 ,
1426+ } ,
1427+ } ) ,
1428+ range_length: Some ( 0 ) ,
1429+ text: "-" . to_string( ) ,
1430+ } ,
1431+ TextDocumentContentChangeEvent {
1432+ range: Some ( Range {
1433+ start: Position {
1434+ line: 31 ,
1435+ character: 0 ,
1436+ } ,
1437+ end: Position {
1438+ line: 31 ,
1439+ character: 0 ,
1440+ } ,
1441+ } ) ,
1442+ range_length: Some ( 0 ) ,
1443+ text: "-" . to_string( ) ,
1444+ } ,
1445+ TextDocumentContentChangeEvent {
1446+ range: Some ( Range {
1447+ start: Position {
1448+ line: 30 ,
1449+ character: 0 ,
1450+ } ,
1451+ end: Position {
1452+ line: 30 ,
1453+ character: 0 ,
1454+ } ,
1455+ } ) ,
1456+ range_length: Some ( 0 ) ,
1457+ text: "-" . to_string( ) ,
1458+ } ,
1459+ TextDocumentContentChangeEvent {
1460+ range: Some ( Range {
1461+ start: Position {
1462+ line: 29 ,
1463+ character: 0 ,
1464+ } ,
1465+ end: Position {
1466+ line: 29 ,
1467+ character: 0 ,
1468+ } ,
1469+ } ) ,
1470+ range_length: Some ( 0 ) ,
1471+ text: "-" . to_string( ) ,
1472+ } ,
1473+ TextDocumentContentChangeEvent {
1474+ range: Some ( Range {
1475+ start: Position {
1476+ line: 28 ,
1477+ character: 0 ,
1478+ } ,
1479+ end: Position {
1480+ line: 28 ,
1481+ character: 0 ,
1482+ } ,
1483+ } ) ,
1484+ range_length: Some ( 0 ) ,
1485+ text: "-" . to_string( ) ,
1486+ } ,
1487+ ] ,
1488+ )
1489+ . await ?;
1490+
1491+ server. shutdown ( ) . await ?;
1492+ reader. abort ( ) ;
1493+
1494+ Ok ( ( ) )
1495+ }
0 commit comments